diff --git a/barretenberg/cpp/pil/vm2/execution.pil b/barretenberg/cpp/pil/vm2/execution.pil index a54aa49a841d..e358df327bc3 100644 --- a/barretenberg/cpp/pil/vm2/execution.pil +++ b/barretenberg/cpp/pil/vm2/execution.pil @@ -13,6 +13,7 @@ include "ecc.pil"; include "poseidon2_hash.pil"; include "poseidon2_perm.pil"; include "scalar_mul.pil"; +include "to_radix.pil"; namespace execution; diff --git a/barretenberg/cpp/pil/vm2/precomputed.pil b/barretenberg/cpp/pil/vm2/precomputed.pil index 9fbc178944d6..1876db3cf825 100644 --- a/barretenberg/cpp/pil/vm2/precomputed.pil +++ b/barretenberg/cpp/pil/vm2/precomputed.pil @@ -81,3 +81,15 @@ pol constant instr_size_in_bytes; // Is used to lookup into the wire instruction spec table which contains the operand decomposition // selectors as well as exec_opcode pol constant sel_range_wire_opcode; + +// Used for getting the number of safe limbs for a given radix. +// The selector is on for 1 < clk <= 256 +pol constant sel_to_radix_safe_limbs; +// Number of safe limbs for a given radix=clk. +pol constant to_radix_safe_limbs; + +// Radix decompositions of P. +pol constant sel_p_decomposition; +pol constant p_decomposition_radix; +pol constant p_decomposition_limb_index; +pol constant p_decomposition_limb; diff --git a/barretenberg/cpp/pil/vm2/scalar_mul.pil b/barretenberg/cpp/pil/vm2/scalar_mul.pil index 965b15a72fea..124e67a63b2d 100644 --- a/barretenberg/cpp/pil/vm2/scalar_mul.pil +++ b/barretenberg/cpp/pil/vm2/scalar_mul.pil @@ -1,4 +1,5 @@ include "ecc.pil"; +include "to_radix.pil"; // Performs scalar_mul with Fr scalars doing the following algorithm: // @@ -102,7 +103,9 @@ namespace scalar_mul; // We start with bit index 253 start * (bit_idx - 253) = 0; - // End can only be 1 when bit_idx is 0. This should be correct because end is bool and bit_idx is being constrained to be 0..254 + // End can only be 1 when bit_idx is 0. + // This does not imply that end will be 1 when bit_idx is zero. The prover can choose to not turn end on + // but then they won't be able to reach an end again in the whole trace, rendering the trace invalid. end * bit_idx = 0; // Next bit index has to be 1 less except on end @@ -112,11 +115,11 @@ namespace scalar_mul; pol commit bit_radix; sel * (bit_radix - 2) = 0; - // #[TO_RADIX] - // sel { scalar, bit, bit_idx, bit_radix } - // in - // to_radix.sel - // { to_radix.input, to_radix.limb, to_radix.limb_index, to_radix.radix }; + #[TO_RADIX] + sel { scalar, bit, bit_idx, bit_radix } + in + to_radix.sel + { to_radix.value, to_radix.limb, to_radix.limb_index, to_radix.radix }; // TEMP COMPUTATION diff --git a/barretenberg/cpp/pil/vm2/to_radix.pil b/barretenberg/cpp/pil/vm2/to_radix.pil new file mode 100644 index 000000000000..766920d0b1d2 --- /dev/null +++ b/barretenberg/cpp/pil/vm2/to_radix.pil @@ -0,0 +1,221 @@ +include "range_check.pil"; + +// Decomposes a field in radixes +// Roughly, what we do is keep track of an accumulator where we reconstruct value using the limbs. We can end when the accumulator is equal to the value (found). +// For overflow protection, we compare the limbs against the p limbs for the given radix. If we reach the last limb (is_unsafe) we assert that we are under p. +// Overflow in the accumulator can only happen in the unsafe limb. After the unsafe limb we have padding limbs, that we assert to be zero. This is used +// because users might want to decompose in more limbs that strictly needed for the radix. +// The following table is non-exhaustive, we do have some extra columns to compute these values. +// +-------+-------+------+--------+------------+------+-------------+----------+------------------+-------+------------+-----------+-------+-----+-----+---------+ +// | value | radix | limb | p_limb | limb_index | acc | acc_under_p | exponent | not_padding_limb | found | safe_limbs | is_unsafe | start | end | sel | not_end | +// +-------+-------+------+--------+------------+------+-------------+----------+------------------+-------+------------+-----------+-------+-----+-----+---------+ +// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +// | 1337 | 10 | 7 | 7 | 0 | 7 | 0 | 1 | 1 | 0 | 76 | 0 | 1 | 0 | 1 | 1 | +// | 1337 | 10 | 3 | 1 | 1 | 37 | 0 | 10 | 1 | 0 | 76 | 0 | 0 | 0 | 1 | 1 | +// | 1337 | 10 | 3 | 6 | 2 | 337 | 1 | 100 | 1 | 0 | 76 | 0 | 0 | 0 | 1 | 1 | +// | 1337 | 10 | 1 | 5 | 3 | 1337 | 1 | 1000 | 1 | 1 | 76 | 0 | 0 | 0 | 1 | 1 | +// | 1337 | 10 | 0 | 9 | 4 | 1337 | 1 | 10000 | 1 | 1 | 76 | 0 | 0 | 0 | 1 | 1 | +// | 1337 | 10 | 0 | 2 | 76 | 1337 | 1 | 10**76 | 1 | 1 | 76 | 1 | 0 | 0 | 1 | 1 | +// | 1337 | 10 | 0 | 0 | 77 | 1337 | 0 | 0 | 0 | 1 | 76 | 0 | 0 | 1 | 1 | 0 | +// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +// +-------+-------+------+--------+------------+------+-------------+----------+------------------+-------+------------+-----------+-------+-----+-----+---------+ +namespace to_radix; + + #[skippable_if] + sel = 0; + + pol commit sel; + sel * (1 - sel) = 0; + + // Inputs to to_radix + pol commit value; + pol commit radix; // Must be 256 >= radix >= 2 + pol commit limb_index; + + // Outputs of to_radix + pol commit limb; + + + // LIFECYCLE + + pol commit start; + start * (1 - start) = 0; + + pol commit end; + end * (1 - end) = 0; + + // end and first_row are NAND + end * precomputed.first_row = 0; + pol LATCH_CONDITION = end + precomputed.first_row; + + #[START_AFTER_LATCH] + sel' * (start' - LATCH_CONDITION) = 0; + + // Selector must be 1 in a start row + #[SELECTOR_ON_START] + start * (1 - sel) = 0; + // Next selector must be current selector unless LATCH_CONDITION + #[SELECTOR_CONSISTENCY] + (sel' - sel) * (1 - LATCH_CONDITION) = 0; + // Selector must be 1 in an end row + end * (1 - sel) = 0; + + // Commited to reduce the degree of expressions + pol commit not_end; + sel * (1 - end) - not_end = 0; + + + // EXPONENTIATION + + pol commit exponent; + // We commit not_padding_limb instead of the more natural padding_limb because it's going to be used in a lookup + pol commit not_padding_limb; + not_padding_limb * (1 - not_padding_limb) = 0; + + // exponent starts at 1 + start * (exponent - 1) = 0; + // next exponent is current exponent * radix unless it's a padding limb + not_end * not_padding_limb' * (exponent * radix - exponent') = 0; + // not_padding_limb starts at 1 + start * (1 - not_padding_limb) = 0; + // next not not_padding_limb is current not_padding_limb unless current limb is unsafe, where it changes to 0 + not_end * ((0 - not_padding_limb) * is_unsafe_limb + not_padding_limb - not_padding_limb') = 0; + + // Padding limbs have zero exponent + (1 - not_padding_limb) * exponent = 0; + + + // ACCUMULATION + + pol commit acc; + pol commit found; + found * (1 - found) = 0; + + // Limb index starts at zero + start * (limb_index - 0) = 0; + + // Limb index must increase + not_end * (limb_index + 1 - limb_index') = 0; + + // Range check limb so we can safely assert that it's less than radix. + #[LIMB_RANGE] + sel { limb } + in + precomputed.sel_range_8 + { precomputed.clk }; + + // Limb should be less than radix + pol commit limb_radix_diff; + sel * (radix - 1 - limb - limb_radix_diff) = 0; + + #[LIMB_LESS_THAN_RADIX_RANGE] + sel { limb_radix_diff } + in + precomputed.sel_range_8 + { precomputed.clk }; + + + // On start, current acc must be equal to limb + start * (acc - limb) = 0; + // Next acc must be current acc + next_exponent*next_limb + not_end * (acc + exponent' * limb' - acc') = 0; + + // found is 1 when value - acc = 0 + pol REM = value - acc; + pol commit rem_inverse; + sel * (REM * (found * (1 - rem_inverse) + rem_inverse) - 1 + found) = 0; + + // when found is 1, next limb is 0 + not_end * found * limb' = 0; + + // We can only enable end when found is one + (1 - found) * end = 0; + + + // OVERFLOW PROTECTION + + pol commit safe_limbs; + + #[FETCH_SAFE_LIMBS] + start { radix, safe_limbs } + in + precomputed.sel_to_radix_safe_limbs + { precomputed.clk, precomputed.to_radix_safe_limbs }; + + pol commit is_unsafe_limb; + is_unsafe_limb * (1 - is_unsafe_limb) = 0; + + // If is_padding_limb, limb is zero + (1 - not_padding_limb) * limb = 0; + // If is_padding_limb, p_limb is zero + (1 - not_padding_limb) * p_limb = 0; + + // is_unsafe_limb is on when and only when limb_index == safe_limbs + pol safety_diff = limb_index - safe_limbs; + pol commit safety_diff_inverse; + sel * (safety_diff * (is_unsafe_limb * (1 - safety_diff_inverse) + safety_diff_inverse) - 1 + is_unsafe_limb) = 0; + + // The limb of the modulus p decomposed by radix at this limb_index + pol commit p_limb; + + #[FETCH_P_LIMB] + not_padding_limb { radix, limb_index, p_limb } + in + precomputed.sel_p_decomposition + { precomputed.p_decomposition_radix, precomputed.p_decomposition_limb_index, precomputed.p_decomposition_limb }; + + // We carry wether the accumulator is under p. If we reach the unsafe limb, we need to ensure that this is true. + pol commit acc_under_p; + acc_under_p * (1 - acc_under_p) = 0; + + // 1 when lt, 0 when gt or equal + pol commit limb_lt_p; + limb_lt_p * (1 - limb_lt_p) = 0; + + pol commit limb_eq_p; + limb_eq_p * (1 - limb_eq_p) = 0; + + // limb_eq_p and limb_lt_p are NAND + limb_eq_p * limb_lt_p = 0; + + // validate limb_lt_p and limb_eq_p + pol commit limb_p_diff; + + pol LIMB_LT_P = p_limb - limb - 1; + pol LIMB_GT_P = limb - p_limb - 1; + // We already need an 8 bit range check for the LT/GT cases. We can reuse that range check + // to validate the EQ case, instead of doing the classical inversion mechanism. + // (limb - p_limb) can go from -255 to +255, so if we multiply by 256 any number in the range + // will be greater than 8 bits except for 0. + pol LIMB_EQ_P = (limb - p_limb) * 256; + + // limb_p_diff = if limb_lt_p {LIMB_LT_P} else if limb_eq_p {LIMB_EQ_P} else {LIMB_GT_P} + limb_lt_p * (LIMB_LT_P - limb_p_diff) = 0; + sel * (1 - limb_lt_p) * ((LIMB_EQ_P - LIMB_GT_P) * limb_eq_p + LIMB_GT_P - limb_p_diff) = 0; + + #[LIMB_P_DIFF_RANGE] + not_padding_limb { limb_p_diff } + in + precomputed.sel_range_8 + { precomputed.clk }; + + // acc_under_p is on start is equal to limb_lt_p + start * (acc_under_p - limb_lt_p) = 0; + // acc_under_p' = limb_eq_p' ? acc_under_p : limb_lt_p' + not_end * ((acc_under_p - limb_lt_p') * limb_eq_p' + limb_lt_p' - acc_under_p') = 0; + + // On the the unsafe limb, we must be under p + #[OVERFLOW_CHECK] + is_unsafe_limb * (1 - acc_under_p) = 0; + + + // CONSTANT CONSISTENCY + + #[CONSTANT_CONSISTENCY_RADIX] + not_end * (radix - radix') = 0; + + #[CONSTANT_CONSISTENCY_VALUE] + not_end * (value - value') = 0; + + #[CONSTANT_CONSISTENCY_SAFE_LIMBS] + not_end * (safe_limbs - safe_limbs') = 0; diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/to_radix.cpp b/barretenberg/cpp/src/barretenberg/vm2/common/to_radix.cpp new file mode 100644 index 000000000000..df68413eaa1c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/common/to_radix.cpp @@ -0,0 +1,39 @@ +#include "barretenberg/vm2/common/to_radix.hpp" + +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/vm2/common/field.hpp" + +namespace bb::avm2 { + +namespace { + +// The little endian decompositions of Fr modulus into limbs for each radix. +// Radix goes up to 256 so we need 257 descompositions. +std::array, 257> create_p_limbs_per_radix() +{ + std::array, 257> limbs_per_radix; + + for (size_t radix = 2; radix < 257; ++radix) { + std::vector p_limbs{}; + p_limbs.reserve(31); + uint256_t p = FF::modulus; + while (p > 0) { + p_limbs.push_back(static_cast(p % radix)); + p /= radix; + } + + limbs_per_radix[radix] = p_limbs; + } + + return limbs_per_radix; +} + +} // namespace + +const std::array, 257>& get_p_limbs_per_radix() +{ + static const std::array, 257> limbs_per_radix = create_p_limbs_per_radix(); + return limbs_per_radix; +} + +} // namespace bb::avm2 diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/to_radix.hpp b/barretenberg/cpp/src/barretenberg/vm2/common/to_radix.hpp new file mode 100644 index 000000000000..1f8a6b9343ee --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/common/to_radix.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include + +namespace bb::avm2 { + +const std::array, 257>& get_p_limbs_per_radix(); + +} // namespace bb::avm2 diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/ecc.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/ecc.test.cpp index 7984de0294cc..6db83cfa2454 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/ecc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/ecc.test.cpp @@ -9,11 +9,13 @@ #include "barretenberg/vm2/generated/relations/lookups_scalar_mul.hpp" #include "barretenberg/vm2/simulation/ecc.hpp" #include "barretenberg/vm2/simulation/events/ecc_events.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" #include "barretenberg/vm2/testing/fixtures.hpp" #include "barretenberg/vm2/testing/macros.hpp" #include "barretenberg/vm2/tracegen/ecc_trace.hpp" #include "barretenberg/vm2/tracegen/lib/lookup_builder.hpp" #include "barretenberg/vm2/tracegen/test_trace_container.hpp" +#include "barretenberg/vm2/tracegen/to_radix_trace.hpp" namespace bb::avm2::constraining { namespace { @@ -24,12 +26,15 @@ using C = Column; using ecc = bb::avm2::ecc; using scalar_mul = bb::avm2::scalar_mul; using EccSimulator = simulation::Ecc; +using ToRadixSimulator = simulation::ToRadix; using simulation::EccAddEvent; using simulation::EventEmitter; using simulation::NoopEventEmitter; using simulation::ScalarMulEvent; +using simulation::ToRadixEvent; using lookup_scalar_mul_double_relation = bb::avm2::lookup_scalar_mul_double_relation; using lookup_scalar_mul_add_relation = bb::avm2::lookup_scalar_mul_add_relation; +using lookup_scalar_mul_to_radix_relation = bb::avm2::lookup_scalar_mul_to_radix_relation; using tracegen::LookupIntoDynamicTableGeneric; // Known good points for P and Q @@ -472,7 +477,10 @@ TEST(ScalarMulConstrainingTest, MulByOne) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF(1); ecc_simulator.scalar_mul(p, scalar); @@ -491,7 +499,10 @@ TEST(ScalarMulConstrainingTest, BasicMul) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -510,7 +521,10 @@ TEST(ScalarMulConstrainingTest, MultipleInvocations) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); ecc_simulator.scalar_mul(p, FF("0x2b01df0ef6d941a826bea23bece8243cbcdc159d5e97fbaa2171f028e05ba9b6")); ecc_simulator.scalar_mul(q, FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09")); @@ -525,11 +539,14 @@ TEST(ScalarMulConstrainingTest, MultipleInvocations) check_relation(trace); } -TEST(ScalarMulConstrainingTest, MulAddInteractions) +TEST(ScalarMulConstrainingTest, MulInteractions) { EventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -539,23 +556,30 @@ TEST(ScalarMulConstrainingTest, MulAddInteractions) }); tracegen::EccTraceBuilder builder; + tracegen::ToRadixTraceBuilder to_radix_builder; builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace); builder.process_add(ecc_add_event_emitter.dump_events(), trace); + to_radix_builder.process(to_radix_event_emitter.dump_events(), trace); LookupIntoDynamicTableGeneric().process(trace); LookupIntoDynamicTableGeneric().process(trace); + LookupIntoDynamicTableGeneric().process(trace); check_relation(trace); check_relation(trace); check_interaction(trace); check_interaction(trace); + check_interaction(trace); } TEST(ScalarMulConstrainingTest, MulAddInteractionsInfinity) { EventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); EmbeddedCurvePoint result = ecc_simulator.scalar_mul(EmbeddedCurvePoint::infinity(), FF(10)); ASSERT(result.is_infinity()); @@ -581,7 +605,10 @@ TEST(ScalarMulConstrainingTest, NegativeMulAddInteractions) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -606,11 +633,42 @@ TEST(ScalarMulConstrainingTest, NegativeMulAddInteractions) "Relation.*SCALAR_MUL_ADD.* ACCUMULATION.* is non-zero"); } +TEST(ScalarMulConstrainingTest, NegativeMulRadixInteractions) +{ + NoopEventEmitter ecc_add_event_emitter; + EventEmitter scalar_mul_event_emitter; + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); + + FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); + ecc_simulator.scalar_mul(p, scalar); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::EccTraceBuilder builder; + builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace); + + EXPECT_THROW_WITH_MESSAGE( + LookupIntoDynamicTableGeneric().process(trace), + "Failed.*SCALAR_MUL_TO_RADIX. Could not find tuple in destination."); + + check_relation(trace); + EXPECT_THROW_WITH_MESSAGE(check_interaction(trace), + "Relation.*SCALAR_MUL_TO_RADIX.* ACCUMULATION.* is non-zero"); +} + TEST(ScalarMulConstrainingTest, NegativeDisableSel) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -631,7 +689,10 @@ TEST(ScalarMulConstrainingTest, NegativeEnableStartFirstRow) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -651,7 +712,10 @@ TEST(ScalarMulConstrainingTest, NegativeMutateScalarOnEnd) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -672,7 +736,10 @@ TEST(ScalarMulConstrainingTest, NegativeMutatePointXOnEnd) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -694,7 +761,10 @@ TEST(ScalarMulConstrainingTest, NegativeMutatePointYOnEnd) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); @@ -716,7 +786,10 @@ TEST(ScalarMulConstrainingTest, NegativeMutatePointInfOnEnd) { NoopEventEmitter ecc_add_event_emitter; EventEmitter scalar_mul_event_emitter; - EccSimulator ecc_simulator(ecc_add_event_emitter, scalar_mul_event_emitter); + NoopEventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + EccSimulator ecc_simulator(to_radix_simulator, ecc_add_event_emitter, scalar_mul_event_emitter); FF scalar = FF("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09"); ecc_simulator.scalar_mul(p, scalar); diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/to_radix.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/to_radix.test.cpp new file mode 100644 index 000000000000..4e45f22b8275 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/to_radix.test.cpp @@ -0,0 +1,347 @@ +#include +#include + +#include "barretenberg/vm/avm/trace/gadgets/range_check.hpp" +#include "barretenberg/vm2/common/aztec_types.hpp" +#include "barretenberg/vm2/constraining/testing/check_relation.hpp" +#include "barretenberg/vm2/generated/flavor_settings.hpp" +#include "barretenberg/vm2/generated/relations/lookups_to_radix.hpp" +#include "barretenberg/vm2/simulation/to_radix.hpp" +#include "barretenberg/vm2/testing/fixtures.hpp" +#include "barretenberg/vm2/testing/macros.hpp" +#include "barretenberg/vm2/tracegen/lib/lookup_builder.hpp" +#include "barretenberg/vm2/tracegen/lib/lookup_into_indexed_by_clk.hpp" +#include "barretenberg/vm2/tracegen/lib/lookup_into_p_decomposition.hpp" +#include "barretenberg/vm2/tracegen/precomputed_trace.hpp" +#include "barretenberg/vm2/tracegen/test_trace_container.hpp" +#include "barretenberg/vm2/tracegen/to_radix_trace.hpp" + +namespace bb::avm2::constraining { +namespace { + +using tracegen::TestTraceContainer; +using FF = AvmFlavorSettings::FF; +using C = Column; +using to_radix = bb::avm2::to_radix; +using ToRadixSimulator = simulation::ToRadix; +using simulation::EventEmitter; +using simulation::ToRadixEvent; +using tracegen::LookupIntoIndexedByClk; +using tracegen::LookupIntoPDecomposition; +using lookup_limb_range = bb::avm2::lookup_to_radix_limb_range_relation; +using lookup_limb_less_than_radix_range = bb::avm2::lookup_to_radix_limb_less_than_radix_range_relation; +using lookup_fetch_safe_limbs = bb::avm2::lookup_to_radix_fetch_safe_limbs_relation; +using lookup_fetch_p_limb = bb::avm2::lookup_to_radix_fetch_p_limb_relation; +using lookup_limb_p_diff_range = bb::avm2::lookup_to_radix_limb_p_diff_range_relation; + +TEST(ToRadixConstrainingTest, EmptyRow) +{ + check_relation(testing::empty_trace()); +} + +TEST(ToRadixConstrainingTest, ToLeBitsBasicTest) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + auto bits = to_radix_simulator.to_le_bits(FF::one(), 254); + + EXPECT_EQ(bits.size(), 254); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 254); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeBitsPMinusOne) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + auto bits = to_radix_simulator.to_le_bits(FF::neg_one(), 254); + + EXPECT_EQ(bits.size(), 254); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 254); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeBitsShortest) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + auto bits = to_radix_simulator.to_le_bits(FF::one(), 1); + + EXPECT_EQ(bits.size(), 1); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 1); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeBitsPadded) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + auto bits = to_radix_simulator.to_le_bits(FF::one(), 500); + + EXPECT_EQ(bits.size(), 500); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 500); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeRadixBasic) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + FF value = FF::one(); + auto bytes = to_radix_simulator.to_le_radix(value, 32, 256); + + auto expected_bytes = value.to_buffer(); + // to_buffer is BE + std::reverse(expected_bytes.begin(), expected_bytes.end()); + EXPECT_EQ(bytes, expected_bytes); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 32); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeRadixPMinusOne) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + FF value = FF::neg_one(); + auto bytes = to_radix_simulator.to_le_radix(value, 32, 256); + + auto expected_bytes = value.to_buffer(); + // to_buffer is BE + std::reverse(expected_bytes.begin(), expected_bytes.end()); + EXPECT_EQ(bytes, expected_bytes); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 32); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeRadixOneByte) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + auto bytes = to_radix_simulator.to_le_radix(FF::one(), 1, 256); + + std::vector expected_bytes = { 1 }; + EXPECT_EQ(bytes, expected_bytes); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 1); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeRadixPadded) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + FF value = FF::neg_one(); + auto bytes = to_radix_simulator.to_le_radix(value, 64, 256); + + auto expected_bytes = value.to_buffer(); + // to_buffer is BE + std::reverse(expected_bytes.begin(), expected_bytes.end()); + expected_bytes.resize(64); + EXPECT_EQ(bytes, expected_bytes); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 64); + check_relation(trace); +} + +TEST(ToRadixConstrainingTest, ToLeBitsInteractions) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + to_radix_simulator.to_le_bits(FF::neg_one(), 254); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder to_radix_builder; + to_radix_builder.process(to_radix_event_emitter.dump_events(), trace); + tracegen::PrecomputedTraceBuilder precomputed_builder; + precomputed_builder.process_misc(trace, 257); + precomputed_builder.process_sel_range_8(trace); + precomputed_builder.process_to_radix_safe_limbs(trace); + precomputed_builder.process_to_radix_p_decompositions(trace); + + LookupIntoIndexedByClk().process(trace); + LookupIntoIndexedByClk().process(trace); + LookupIntoIndexedByClk().process(trace); + LookupIntoPDecomposition().process(trace); + LookupIntoIndexedByClk().process(trace); + + check_relation(trace); + check_interaction(trace); + check_interaction(trace); + check_interaction(trace); + check_interaction(trace); + check_interaction(trace); +} + +TEST(ToRadixConstrainingTest, ToLeRadixInteractions) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + to_radix_simulator.to_le_radix(FF::neg_one(), 32, 256); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder to_radix_builder; + to_radix_builder.process(to_radix_event_emitter.dump_events(), trace); + tracegen::PrecomputedTraceBuilder precomputed_builder; + + precomputed_builder.process_misc(trace, 257); + precomputed_builder.process_sel_range_8(trace); + precomputed_builder.process_to_radix_safe_limbs(trace); + precomputed_builder.process_to_radix_p_decompositions(trace); + + LookupIntoIndexedByClk().process(trace); + LookupIntoIndexedByClk().process(trace); + LookupIntoIndexedByClk().process(trace); + LookupIntoPDecomposition().process(trace); + LookupIntoIndexedByClk().process(trace); + + check_relation(trace); + check_interaction(trace); + check_interaction(trace); + check_interaction(trace); + check_interaction(trace); + check_interaction(trace); +} + +TEST(ToRadixConstrainingTest, NegativeOverflowCheck) +{ + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + std::vector modulus_le_bits(256, 0); + for (size_t i = 0; i < 256; i++) { + modulus_le_bits[i] = static_cast(FF::modulus.get_bit(i)); + } + + ToRadixEvent event = { .value = FF::zero(), .radix = 2, .limbs = modulus_le_bits }; + std::vector events = { event }; + + tracegen::ToRadixTraceBuilder builder; + builder.process(events, trace); + + EXPECT_THROW_WITH_MESSAGE(check_relation(trace, to_radix::SR_OVERFLOW_CHECK), "OVERFLOW_CHECK"); +} + +TEST(ToRadixConstrainingTest, NegativeConsistency) +{ + EventEmitter to_radix_event_emitter; + + ToRadixSimulator to_radix_simulator(to_radix_event_emitter); + + to_radix_simulator.to_le_radix(FF(256), 32, 256); + + TestTraceContainer trace = TestTraceContainer::from_rows({ + { .precomputed_first_row = 1 }, + }); + + tracegen::ToRadixTraceBuilder builder; + builder.process(to_radix_event_emitter.dump_events(), trace); + + // Disable the selector in the middle + trace.set(Column::to_radix_sel, 6, 0); + + EXPECT_THROW_WITH_MESSAGE(check_relation(trace, to_radix::SR_SELECTOR_CONSISTENCY), + "SELECTOR_CONSISTENCY"); + + // Mutate the radix + trace.set(Column::to_radix_radix, 5, 200); + + EXPECT_THROW_WITH_MESSAGE(check_relation(trace, to_radix::SR_CONSTANT_CONSISTENCY_RADIX), + "CONSTANT_CONSISTENCY_RADIX"); + + // Mutate the value + trace.set(Column::to_radix_value, 4, 27); + + EXPECT_THROW_WITH_MESSAGE(check_relation(trace, to_radix::SR_CONSTANT_CONSISTENCY_VALUE), + "CONSTANT_CONSISTENCY_VALUE"); + + // Mutate the safe_limbs + trace.set(Column::to_radix_safe_limbs, 3, 200); + + EXPECT_THROW_WITH_MESSAGE(check_relation(trace, to_radix::SR_CONSTANT_CONSISTENCY_SAFE_LIMBS), + "CONSTANT_CONSISTENCY_SAFE_LIMBS"); +} + +} // namespace + +} // namespace bb::avm2::constraining diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp index 50245ede1af9..87555864890a 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp @@ -9,17 +9,17 @@ namespace bb::avm2 { // The entities that will be used in the flavor. // clang-format off -#define AVM2_PRECOMPUTED_ENTITIES precomputed_as_unary, precomputed_bitwise_input_a, precomputed_bitwise_input_b, precomputed_bitwise_op_id, precomputed_bitwise_output, precomputed_clk, precomputed_exec_opcode, precomputed_first_row, precomputed_instr_size_in_bytes, precomputed_integral_tag_length, precomputed_power_of_2, precomputed_sel_bitwise, precomputed_sel_integral_tag, precomputed_sel_op_dc_0, precomputed_sel_op_dc_1, precomputed_sel_op_dc_10, precomputed_sel_op_dc_11, precomputed_sel_op_dc_12, precomputed_sel_op_dc_13, precomputed_sel_op_dc_14, precomputed_sel_op_dc_15, precomputed_sel_op_dc_16, precomputed_sel_op_dc_17, precomputed_sel_op_dc_2, precomputed_sel_op_dc_3, precomputed_sel_op_dc_4, precomputed_sel_op_dc_5, precomputed_sel_op_dc_6, precomputed_sel_op_dc_7, precomputed_sel_op_dc_8, precomputed_sel_op_dc_9, precomputed_sel_range_16, precomputed_sel_range_8, precomputed_sel_range_wire_opcode, precomputed_sel_sha256_compression, precomputed_sel_unary, precomputed_sha256_compression_round_constant, precomputed_zero -#define AVM2_WIRE_ENTITIES execution_input, alu_dst_addr, alu_ia, alu_ia_addr, alu_ib, alu_ib_addr, alu_ic, alu_op, alu_sel_op_add, bc_decomposition_abs_diff, bc_decomposition_bytes, bc_decomposition_bytes_pc_plus_1, bc_decomposition_bytes_pc_plus_10, bc_decomposition_bytes_pc_plus_11, bc_decomposition_bytes_pc_plus_12, bc_decomposition_bytes_pc_plus_13, bc_decomposition_bytes_pc_plus_14, bc_decomposition_bytes_pc_plus_15, bc_decomposition_bytes_pc_plus_16, bc_decomposition_bytes_pc_plus_17, bc_decomposition_bytes_pc_plus_18, bc_decomposition_bytes_pc_plus_19, bc_decomposition_bytes_pc_plus_2, bc_decomposition_bytes_pc_plus_20, bc_decomposition_bytes_pc_plus_21, bc_decomposition_bytes_pc_plus_22, bc_decomposition_bytes_pc_plus_23, bc_decomposition_bytes_pc_plus_24, bc_decomposition_bytes_pc_plus_25, bc_decomposition_bytes_pc_plus_26, bc_decomposition_bytes_pc_plus_27, bc_decomposition_bytes_pc_plus_28, bc_decomposition_bytes_pc_plus_29, bc_decomposition_bytes_pc_plus_3, bc_decomposition_bytes_pc_plus_30, bc_decomposition_bytes_pc_plus_31, bc_decomposition_bytes_pc_plus_32, bc_decomposition_bytes_pc_plus_33, bc_decomposition_bytes_pc_plus_34, bc_decomposition_bytes_pc_plus_35, bc_decomposition_bytes_pc_plus_36, bc_decomposition_bytes_pc_plus_4, bc_decomposition_bytes_pc_plus_5, bc_decomposition_bytes_pc_plus_6, bc_decomposition_bytes_pc_plus_7, bc_decomposition_bytes_pc_plus_8, bc_decomposition_bytes_pc_plus_9, bc_decomposition_bytes_rem_inv, bc_decomposition_bytes_rem_min_one_inv, bc_decomposition_bytes_remaining, bc_decomposition_bytes_to_read, bc_decomposition_bytes_to_read_unary, bc_decomposition_id, bc_decomposition_last_of_contract, bc_decomposition_packed_field, bc_decomposition_pc, bc_decomposition_sel, bc_decomposition_sel_overflow_correction_needed, bc_decomposition_sel_packed, bc_decomposition_sel_pc_plus_1, bc_decomposition_sel_pc_plus_10, bc_decomposition_sel_pc_plus_11, bc_decomposition_sel_pc_plus_12, bc_decomposition_sel_pc_plus_13, bc_decomposition_sel_pc_plus_14, bc_decomposition_sel_pc_plus_15, bc_decomposition_sel_pc_plus_16, bc_decomposition_sel_pc_plus_17, bc_decomposition_sel_pc_plus_18, bc_decomposition_sel_pc_plus_19, bc_decomposition_sel_pc_plus_2, bc_decomposition_sel_pc_plus_20, bc_decomposition_sel_pc_plus_21, bc_decomposition_sel_pc_plus_22, bc_decomposition_sel_pc_plus_23, bc_decomposition_sel_pc_plus_24, bc_decomposition_sel_pc_plus_25, bc_decomposition_sel_pc_plus_26, bc_decomposition_sel_pc_plus_27, bc_decomposition_sel_pc_plus_28, bc_decomposition_sel_pc_plus_29, bc_decomposition_sel_pc_plus_3, bc_decomposition_sel_pc_plus_30, bc_decomposition_sel_pc_plus_31, bc_decomposition_sel_pc_plus_32, bc_decomposition_sel_pc_plus_33, bc_decomposition_sel_pc_plus_34, bc_decomposition_sel_pc_plus_35, bc_decomposition_sel_pc_plus_36, bc_decomposition_sel_pc_plus_4, bc_decomposition_sel_pc_plus_5, bc_decomposition_sel_pc_plus_6, bc_decomposition_sel_pc_plus_7, bc_decomposition_sel_pc_plus_8, bc_decomposition_sel_pc_plus_9, bc_hashing_bytecode_id, bc_hashing_incremental_hash, bc_hashing_latch, bc_hashing_output_hash, bc_hashing_packed_field, bc_hashing_pc_index, bc_hashing_sel, bc_hashing_start, bc_retrieval_address, bc_retrieval_artifact_hash, bc_retrieval_bytecode_id, bc_retrieval_class_id, bc_retrieval_deployer_addr, bc_retrieval_err, bc_retrieval_incoming_viewing_key_x, bc_retrieval_incoming_viewing_key_y, bc_retrieval_init_hash, bc_retrieval_nullifier_key_x, bc_retrieval_nullifier_key_y, bc_retrieval_outgoing_viewing_key_x, bc_retrieval_outgoing_viewing_key_y, bc_retrieval_private_function_root, bc_retrieval_public_bytecode_commitment, bc_retrieval_salt, bc_retrieval_sel, bc_retrieval_siloed_address, bc_retrieval_tagging_key_x, bc_retrieval_tagging_key_y, bitwise_acc_ia, bitwise_acc_ib, bitwise_acc_ic, bitwise_ctr, bitwise_ctr_inv, bitwise_ctr_min_one_inv, bitwise_ia_byte, bitwise_ib_byte, bitwise_ic_byte, bitwise_last, bitwise_op_id, bitwise_sel, bitwise_start, bitwise_tag, class_id_derivation_artifact_hash, class_id_derivation_class_id, class_id_derivation_private_function_root, class_id_derivation_public_bytecode_commitment, class_id_derivation_sel, class_id_derivation_temp_constant_for_lookup, ecc_add_op, ecc_double_op, ecc_inv_2_p_y, ecc_inv_x_diff, ecc_inv_y_diff, ecc_lambda, ecc_p_is_inf, ecc_p_x, ecc_p_y, ecc_q_is_inf, ecc_q_x, ecc_q_y, ecc_r_is_inf, ecc_r_x, ecc_r_y, ecc_result_infinity, ecc_sel, ecc_x_match, ecc_y_match, execution_addressing_error_idx, execution_addressing_error_kind, execution_base_address_tag, execution_base_address_val, execution_bytecode_id, execution_clk, execution_ex_opcode, execution_indirect, execution_last, execution_op1, execution_op1_after_relative, execution_op2, execution_op2_after_relative, execution_op3, execution_op3_after_relative, execution_op4, execution_op4_after_relative, execution_pc, execution_rop1, execution_rop2, execution_rop3, execution_rop4, execution_sel, execution_sel_addressing_error, execution_sel_op1_is_address, execution_sel_op2_is_address, execution_sel_op3_is_address, execution_sel_op4_is_address, instr_fetching_bd0, instr_fetching_bd1, instr_fetching_bd10, instr_fetching_bd11, instr_fetching_bd12, instr_fetching_bd13, instr_fetching_bd14, instr_fetching_bd15, instr_fetching_bd16, instr_fetching_bd17, instr_fetching_bd18, instr_fetching_bd19, instr_fetching_bd2, instr_fetching_bd20, instr_fetching_bd21, instr_fetching_bd22, instr_fetching_bd23, instr_fetching_bd24, instr_fetching_bd25, instr_fetching_bd26, instr_fetching_bd27, instr_fetching_bd28, instr_fetching_bd29, instr_fetching_bd3, instr_fetching_bd30, instr_fetching_bd31, instr_fetching_bd32, instr_fetching_bd33, instr_fetching_bd34, instr_fetching_bd35, instr_fetching_bd36, instr_fetching_bd4, instr_fetching_bd5, instr_fetching_bd6, instr_fetching_bd7, instr_fetching_bd8, instr_fetching_bd9, instr_fetching_bytecode_id, instr_fetching_exec_opcode, instr_fetching_indirect, instr_fetching_instr_size_in_bytes, instr_fetching_op1, instr_fetching_op2, instr_fetching_op3, instr_fetching_op4, instr_fetching_op5, instr_fetching_op6, instr_fetching_op7, instr_fetching_pc, instr_fetching_sel, instr_fetching_sel_op_dc_0, instr_fetching_sel_op_dc_1, instr_fetching_sel_op_dc_10, instr_fetching_sel_op_dc_11, instr_fetching_sel_op_dc_12, instr_fetching_sel_op_dc_13, instr_fetching_sel_op_dc_14, instr_fetching_sel_op_dc_15, instr_fetching_sel_op_dc_16, instr_fetching_sel_op_dc_17, instr_fetching_sel_op_dc_2, instr_fetching_sel_op_dc_3, instr_fetching_sel_op_dc_4, instr_fetching_sel_op_dc_5, instr_fetching_sel_op_dc_6, instr_fetching_sel_op_dc_7, instr_fetching_sel_op_dc_8, instr_fetching_sel_op_dc_9, poseidon2_hash_a_0, poseidon2_hash_a_1, poseidon2_hash_a_2, poseidon2_hash_a_3, poseidon2_hash_b_0, poseidon2_hash_b_1, poseidon2_hash_b_2, poseidon2_hash_b_3, poseidon2_hash_end, poseidon2_hash_input_0, poseidon2_hash_input_1, poseidon2_hash_input_2, poseidon2_hash_input_len, poseidon2_hash_num_perm_rounds_rem, poseidon2_hash_num_perm_rounds_rem_inv, poseidon2_hash_output, poseidon2_hash_padding, poseidon2_hash_sel, poseidon2_hash_start, poseidon2_perm_B_10_0, poseidon2_perm_B_10_1, poseidon2_perm_B_10_2, poseidon2_perm_B_10_3, poseidon2_perm_B_11_0, poseidon2_perm_B_11_1, poseidon2_perm_B_11_2, poseidon2_perm_B_11_3, poseidon2_perm_B_12_0, poseidon2_perm_B_12_1, poseidon2_perm_B_12_2, poseidon2_perm_B_12_3, poseidon2_perm_B_13_0, poseidon2_perm_B_13_1, poseidon2_perm_B_13_2, poseidon2_perm_B_13_3, poseidon2_perm_B_14_0, poseidon2_perm_B_14_1, poseidon2_perm_B_14_2, poseidon2_perm_B_14_3, poseidon2_perm_B_15_0, poseidon2_perm_B_15_1, poseidon2_perm_B_15_2, poseidon2_perm_B_15_3, poseidon2_perm_B_16_0, poseidon2_perm_B_16_1, poseidon2_perm_B_16_2, poseidon2_perm_B_16_3, poseidon2_perm_B_17_0, poseidon2_perm_B_17_1, poseidon2_perm_B_17_2, poseidon2_perm_B_17_3, poseidon2_perm_B_18_0, poseidon2_perm_B_18_1, poseidon2_perm_B_18_2, poseidon2_perm_B_18_3, poseidon2_perm_B_19_0, poseidon2_perm_B_19_1, poseidon2_perm_B_19_2, poseidon2_perm_B_19_3, poseidon2_perm_B_20_0, poseidon2_perm_B_20_1, poseidon2_perm_B_20_2, poseidon2_perm_B_20_3, poseidon2_perm_B_21_0, poseidon2_perm_B_21_1, poseidon2_perm_B_21_2, poseidon2_perm_B_21_3, poseidon2_perm_B_22_0, poseidon2_perm_B_22_1, poseidon2_perm_B_22_2, poseidon2_perm_B_22_3, poseidon2_perm_B_23_0, poseidon2_perm_B_23_1, poseidon2_perm_B_23_2, poseidon2_perm_B_23_3, poseidon2_perm_B_24_0, poseidon2_perm_B_24_1, poseidon2_perm_B_24_2, poseidon2_perm_B_24_3, poseidon2_perm_B_25_0, poseidon2_perm_B_25_1, poseidon2_perm_B_25_2, poseidon2_perm_B_25_3, poseidon2_perm_B_26_0, poseidon2_perm_B_26_1, poseidon2_perm_B_26_2, poseidon2_perm_B_26_3, poseidon2_perm_B_27_0, poseidon2_perm_B_27_1, poseidon2_perm_B_27_2, poseidon2_perm_B_27_3, poseidon2_perm_B_28_0, poseidon2_perm_B_28_1, poseidon2_perm_B_28_2, poseidon2_perm_B_28_3, poseidon2_perm_B_29_0, poseidon2_perm_B_29_1, poseidon2_perm_B_29_2, poseidon2_perm_B_29_3, poseidon2_perm_B_30_0, poseidon2_perm_B_30_1, poseidon2_perm_B_30_2, poseidon2_perm_B_30_3, poseidon2_perm_B_31_0, poseidon2_perm_B_31_1, poseidon2_perm_B_31_2, poseidon2_perm_B_31_3, poseidon2_perm_B_32_0, poseidon2_perm_B_32_1, poseidon2_perm_B_32_2, poseidon2_perm_B_32_3, poseidon2_perm_B_33_0, poseidon2_perm_B_33_1, poseidon2_perm_B_33_2, poseidon2_perm_B_33_3, poseidon2_perm_B_34_0, poseidon2_perm_B_34_1, poseidon2_perm_B_34_2, poseidon2_perm_B_34_3, poseidon2_perm_B_35_0, poseidon2_perm_B_35_1, poseidon2_perm_B_35_2, poseidon2_perm_B_35_3, poseidon2_perm_B_36_0, poseidon2_perm_B_36_1, poseidon2_perm_B_36_2, poseidon2_perm_B_36_3, poseidon2_perm_B_37_0, poseidon2_perm_B_37_1, poseidon2_perm_B_37_2, poseidon2_perm_B_37_3, poseidon2_perm_B_38_0, poseidon2_perm_B_38_1, poseidon2_perm_B_38_2, poseidon2_perm_B_38_3, poseidon2_perm_B_39_0, poseidon2_perm_B_39_1, poseidon2_perm_B_39_2, poseidon2_perm_B_39_3, poseidon2_perm_B_40_0, poseidon2_perm_B_40_1, poseidon2_perm_B_40_2, poseidon2_perm_B_40_3, poseidon2_perm_B_41_0, poseidon2_perm_B_41_1, poseidon2_perm_B_41_2, poseidon2_perm_B_41_3, poseidon2_perm_B_42_0, poseidon2_perm_B_42_1, poseidon2_perm_B_42_2, poseidon2_perm_B_42_3, poseidon2_perm_B_43_0, poseidon2_perm_B_43_1, poseidon2_perm_B_43_2, poseidon2_perm_B_43_3, poseidon2_perm_B_44_0, poseidon2_perm_B_44_1, poseidon2_perm_B_44_2, poseidon2_perm_B_44_3, poseidon2_perm_B_45_0, poseidon2_perm_B_45_1, poseidon2_perm_B_45_2, poseidon2_perm_B_45_3, poseidon2_perm_B_46_0, poseidon2_perm_B_46_1, poseidon2_perm_B_46_2, poseidon2_perm_B_46_3, poseidon2_perm_B_47_0, poseidon2_perm_B_47_1, poseidon2_perm_B_47_2, poseidon2_perm_B_47_3, poseidon2_perm_B_48_0, poseidon2_perm_B_48_1, poseidon2_perm_B_48_2, poseidon2_perm_B_48_3, poseidon2_perm_B_49_0, poseidon2_perm_B_49_1, poseidon2_perm_B_49_2, poseidon2_perm_B_49_3, poseidon2_perm_B_4_0, poseidon2_perm_B_4_1, poseidon2_perm_B_4_2, poseidon2_perm_B_4_3, poseidon2_perm_B_50_0, poseidon2_perm_B_50_1, poseidon2_perm_B_50_2, poseidon2_perm_B_50_3, poseidon2_perm_B_51_0, poseidon2_perm_B_51_1, poseidon2_perm_B_51_2, poseidon2_perm_B_51_3, poseidon2_perm_B_52_0, poseidon2_perm_B_52_1, poseidon2_perm_B_52_2, poseidon2_perm_B_52_3, poseidon2_perm_B_53_0, poseidon2_perm_B_53_1, poseidon2_perm_B_53_2, poseidon2_perm_B_53_3, poseidon2_perm_B_54_0, poseidon2_perm_B_54_1, poseidon2_perm_B_54_2, poseidon2_perm_B_54_3, poseidon2_perm_B_55_0, poseidon2_perm_B_55_1, poseidon2_perm_B_55_2, poseidon2_perm_B_55_3, poseidon2_perm_B_56_0, poseidon2_perm_B_56_1, poseidon2_perm_B_56_2, poseidon2_perm_B_56_3, poseidon2_perm_B_57_0, poseidon2_perm_B_57_1, poseidon2_perm_B_57_2, poseidon2_perm_B_57_3, poseidon2_perm_B_58_0, poseidon2_perm_B_58_1, poseidon2_perm_B_58_2, poseidon2_perm_B_58_3, poseidon2_perm_B_59_0, poseidon2_perm_B_59_1, poseidon2_perm_B_59_2, poseidon2_perm_B_59_3, poseidon2_perm_B_5_0, poseidon2_perm_B_5_1, poseidon2_perm_B_5_2, poseidon2_perm_B_5_3, poseidon2_perm_B_6_0, poseidon2_perm_B_6_1, poseidon2_perm_B_6_2, poseidon2_perm_B_6_3, poseidon2_perm_B_7_0, poseidon2_perm_B_7_1, poseidon2_perm_B_7_2, poseidon2_perm_B_7_3, poseidon2_perm_B_8_0, poseidon2_perm_B_8_1, poseidon2_perm_B_8_2, poseidon2_perm_B_8_3, poseidon2_perm_B_9_0, poseidon2_perm_B_9_1, poseidon2_perm_B_9_2, poseidon2_perm_B_9_3, poseidon2_perm_EXT_LAYER_4, poseidon2_perm_EXT_LAYER_5, poseidon2_perm_EXT_LAYER_6, poseidon2_perm_EXT_LAYER_7, poseidon2_perm_T_0_4, poseidon2_perm_T_0_5, poseidon2_perm_T_0_6, poseidon2_perm_T_0_7, poseidon2_perm_T_1_4, poseidon2_perm_T_1_5, poseidon2_perm_T_1_6, poseidon2_perm_T_1_7, poseidon2_perm_T_2_4, poseidon2_perm_T_2_5, poseidon2_perm_T_2_6, poseidon2_perm_T_2_7, poseidon2_perm_T_3_4, poseidon2_perm_T_3_5, poseidon2_perm_T_3_6, poseidon2_perm_T_3_7, poseidon2_perm_T_60_4, poseidon2_perm_T_60_5, poseidon2_perm_T_60_6, poseidon2_perm_T_60_7, poseidon2_perm_T_61_4, poseidon2_perm_T_61_5, poseidon2_perm_T_61_6, poseidon2_perm_T_61_7, poseidon2_perm_T_62_4, poseidon2_perm_T_62_5, poseidon2_perm_T_62_6, poseidon2_perm_T_62_7, poseidon2_perm_T_63_4, poseidon2_perm_T_63_5, poseidon2_perm_T_63_6, poseidon2_perm_T_63_7, poseidon2_perm_a_0, poseidon2_perm_a_1, poseidon2_perm_a_2, poseidon2_perm_a_3, poseidon2_perm_b_0, poseidon2_perm_b_1, poseidon2_perm_b_2, poseidon2_perm_b_3, poseidon2_perm_sel, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_rng_chk_bits, range_check_sel, range_check_sel_r0_16_bit_rng_lookup, range_check_sel_r1_16_bit_rng_lookup, range_check_sel_r2_16_bit_rng_lookup, range_check_sel_r3_16_bit_rng_lookup, range_check_sel_r4_16_bit_rng_lookup, range_check_sel_r5_16_bit_rng_lookup, range_check_sel_r6_16_bit_rng_lookup, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, scalar_mul_bit, scalar_mul_bit_idx, scalar_mul_bit_radix, scalar_mul_end, scalar_mul_not_end, scalar_mul_point_inf, scalar_mul_point_x, scalar_mul_point_y, scalar_mul_res_inf, scalar_mul_res_x, scalar_mul_res_y, scalar_mul_scalar, scalar_mul_sel, scalar_mul_should_add, scalar_mul_start, scalar_mul_temp_inf, scalar_mul_temp_x, scalar_mul_temp_y, sha256_a, sha256_a_and_b, sha256_a_and_b_xor_a_and_c, sha256_a_and_c, sha256_a_rotr_13, sha256_a_rotr_2, sha256_a_rotr_22, sha256_a_rotr_2_xor_a_rotr_13, sha256_and_sel, sha256_b, sha256_b_and_c, sha256_c, sha256_ch, sha256_clk, sha256_computed_w_lhs, sha256_computed_w_rhs, sha256_d, sha256_e, sha256_e_and_f, sha256_e_rotr_11, sha256_e_rotr_25, sha256_e_rotr_6, sha256_e_rotr_6_xor_e_rotr_11, sha256_f, sha256_g, sha256_h, sha256_helper_w0, sha256_helper_w1, sha256_helper_w10, sha256_helper_w11, sha256_helper_w12, sha256_helper_w13, sha256_helper_w14, sha256_helper_w15, sha256_helper_w2, sha256_helper_w3, sha256_helper_w4, sha256_helper_w5, sha256_helper_w6, sha256_helper_w7, sha256_helper_w8, sha256_helper_w9, sha256_init_a, sha256_init_b, sha256_init_c, sha256_init_d, sha256_init_e, sha256_init_f, sha256_init_g, sha256_init_h, sha256_input_offset, sha256_is_input_round, sha256_latch, sha256_lhs_a_13, sha256_lhs_a_2, sha256_lhs_a_22, sha256_lhs_e_11, sha256_lhs_e_25, sha256_lhs_e_6, sha256_lhs_w_10, sha256_lhs_w_17, sha256_lhs_w_18, sha256_lhs_w_19, sha256_lhs_w_3, sha256_lhs_w_7, sha256_maj, sha256_next_a_lhs, sha256_next_a_rhs, sha256_next_e_lhs, sha256_next_e_rhs, sha256_not_e, sha256_not_e_and_g, sha256_output_a_lhs, sha256_output_a_rhs, sha256_output_b_lhs, sha256_output_b_rhs, sha256_output_c_lhs, sha256_output_c_rhs, sha256_output_d_lhs, sha256_output_d_rhs, sha256_output_e_lhs, sha256_output_e_rhs, sha256_output_f_lhs, sha256_output_f_rhs, sha256_output_g_lhs, sha256_output_g_rhs, sha256_output_h_lhs, sha256_output_h_rhs, sha256_output_offset, sha256_perform_round, sha256_rhs_a_13, sha256_rhs_a_2, sha256_rhs_a_22, sha256_rhs_e_11, sha256_rhs_e_25, sha256_rhs_e_6, sha256_rhs_w_10, sha256_rhs_w_17, sha256_rhs_w_18, sha256_rhs_w_19, sha256_rhs_w_3, sha256_rhs_w_7, sha256_round_constant, sha256_round_count, sha256_rounds_remaining, sha256_rounds_remaining_inv, sha256_s_0, sha256_s_1, sha256_sel, sha256_start, sha256_state_offset, sha256_w, sha256_w_15_rotr_18, sha256_w_15_rotr_7, sha256_w_15_rotr_7_xor_w_15_rotr_18, sha256_w_15_rshift_3, sha256_w_2_rotr_17, sha256_w_2_rotr_17_xor_w_2_rotr_19, sha256_w_2_rotr_19, sha256_w_2_rshift_10, sha256_w_s_0, sha256_w_s_1, sha256_xor_sel, lookup_bc_decomposition_bytes_are_bytes_counts, lookup_bc_decomposition_abs_diff_is_u16_counts, lookup_bc_decomposition_bytes_to_read_as_unary_counts, lookup_poseidon2_hash_poseidon2_perm_counts, lookup_bc_hashing_get_packed_field_counts, lookup_bc_hashing_iv_is_len_counts, lookup_bc_hashing_poseidon2_hash_counts, lookup_bc_retrieval_class_id_derivation_counts, lookup_bc_retrieval_bytecode_hash_is_correct_counts, lookup_instr_fetching_bytes_from_bc_dec_counts, lookup_instr_fetching_wire_instruction_info_counts, lookup_class_id_derivation_class_id_poseidon2_0_counts, lookup_class_id_derivation_class_id_poseidon2_1_counts, lookup_range_check_dyn_rng_chk_pow_2_counts, lookup_range_check_dyn_diff_is_u16_counts, lookup_range_check_r0_is_u16_counts, lookup_range_check_r1_is_u16_counts, lookup_range_check_r2_is_u16_counts, lookup_range_check_r3_is_u16_counts, lookup_range_check_r4_is_u16_counts, lookup_range_check_r5_is_u16_counts, lookup_range_check_r6_is_u16_counts, lookup_range_check_r7_is_u16_counts, lookup_bitwise_integral_tag_length_counts, lookup_bitwise_byte_operations_counts, lookup_sha256_round_constant_counts, lookup_scalar_mul_double_counts, lookup_scalar_mul_add_counts -#define AVM2_DERIVED_WITNESS_ENTITIES lookup_bc_decomposition_bytes_are_bytes_inv, lookup_bc_decomposition_abs_diff_is_u16_inv, lookup_bc_decomposition_bytes_to_read_as_unary_inv, lookup_poseidon2_hash_poseidon2_perm_inv, lookup_bc_hashing_get_packed_field_inv, lookup_bc_hashing_iv_is_len_inv, lookup_bc_hashing_poseidon2_hash_inv, lookup_bc_retrieval_class_id_derivation_inv, lookup_bc_retrieval_bytecode_hash_is_correct_inv, lookup_instr_fetching_bytes_from_bc_dec_inv, lookup_instr_fetching_wire_instruction_info_inv, lookup_class_id_derivation_class_id_poseidon2_0_inv, lookup_class_id_derivation_class_id_poseidon2_1_inv, lookup_range_check_dyn_rng_chk_pow_2_inv, lookup_range_check_dyn_diff_is_u16_inv, lookup_range_check_r0_is_u16_inv, lookup_range_check_r1_is_u16_inv, lookup_range_check_r2_is_u16_inv, lookup_range_check_r3_is_u16_inv, lookup_range_check_r4_is_u16_inv, lookup_range_check_r5_is_u16_inv, lookup_range_check_r6_is_u16_inv, lookup_range_check_r7_is_u16_inv, lookup_bitwise_integral_tag_length_inv, lookup_bitwise_byte_operations_inv, lookup_sha256_round_constant_inv, lookup_scalar_mul_double_inv, lookup_scalar_mul_add_inv -#define AVM2_SHIFTED_ENTITIES bc_decomposition_bytes_shift, bc_decomposition_bytes_pc_plus_1_shift, bc_decomposition_bytes_pc_plus_10_shift, bc_decomposition_bytes_pc_plus_11_shift, bc_decomposition_bytes_pc_plus_12_shift, bc_decomposition_bytes_pc_plus_13_shift, bc_decomposition_bytes_pc_plus_14_shift, bc_decomposition_bytes_pc_plus_15_shift, bc_decomposition_bytes_pc_plus_16_shift, bc_decomposition_bytes_pc_plus_17_shift, bc_decomposition_bytes_pc_plus_18_shift, bc_decomposition_bytes_pc_plus_19_shift, bc_decomposition_bytes_pc_plus_2_shift, bc_decomposition_bytes_pc_plus_20_shift, bc_decomposition_bytes_pc_plus_21_shift, bc_decomposition_bytes_pc_plus_22_shift, bc_decomposition_bytes_pc_plus_23_shift, bc_decomposition_bytes_pc_plus_24_shift, bc_decomposition_bytes_pc_plus_25_shift, bc_decomposition_bytes_pc_plus_26_shift, bc_decomposition_bytes_pc_plus_27_shift, bc_decomposition_bytes_pc_plus_28_shift, bc_decomposition_bytes_pc_plus_29_shift, bc_decomposition_bytes_pc_plus_3_shift, bc_decomposition_bytes_pc_plus_30_shift, bc_decomposition_bytes_pc_plus_31_shift, bc_decomposition_bytes_pc_plus_32_shift, bc_decomposition_bytes_pc_plus_33_shift, bc_decomposition_bytes_pc_plus_34_shift, bc_decomposition_bytes_pc_plus_35_shift, bc_decomposition_bytes_pc_plus_4_shift, bc_decomposition_bytes_pc_plus_5_shift, bc_decomposition_bytes_pc_plus_6_shift, bc_decomposition_bytes_pc_plus_7_shift, bc_decomposition_bytes_pc_plus_8_shift, bc_decomposition_bytes_pc_plus_9_shift, bc_decomposition_bytes_remaining_shift, bc_decomposition_id_shift, bc_decomposition_pc_shift, bc_decomposition_sel_shift, bc_hashing_bytecode_id_shift, bc_hashing_incremental_hash_shift, bc_hashing_pc_index_shift, bc_hashing_sel_shift, bc_hashing_start_shift, bitwise_acc_ia_shift, bitwise_acc_ib_shift, bitwise_acc_ic_shift, bitwise_ctr_shift, bitwise_op_id_shift, execution_sel_shift, poseidon2_hash_a_0_shift, poseidon2_hash_a_1_shift, poseidon2_hash_a_2_shift, poseidon2_hash_a_3_shift, poseidon2_hash_input_0_shift, poseidon2_hash_input_1_shift, poseidon2_hash_input_2_shift, poseidon2_hash_num_perm_rounds_rem_shift, poseidon2_hash_output_shift, poseidon2_hash_sel_shift, poseidon2_hash_start_shift, scalar_mul_bit_idx_shift, scalar_mul_point_inf_shift, scalar_mul_point_x_shift, scalar_mul_point_y_shift, scalar_mul_res_inf_shift, scalar_mul_res_x_shift, scalar_mul_res_y_shift, scalar_mul_scalar_shift, scalar_mul_sel_shift, scalar_mul_start_shift, scalar_mul_temp_inf_shift, scalar_mul_temp_x_shift, scalar_mul_temp_y_shift, sha256_a_shift, sha256_b_shift, sha256_c_shift, sha256_d_shift, sha256_e_shift, sha256_f_shift, sha256_g_shift, sha256_h_shift, sha256_helper_w0_shift, sha256_helper_w1_shift, sha256_helper_w10_shift, sha256_helper_w11_shift, sha256_helper_w12_shift, sha256_helper_w13_shift, sha256_helper_w14_shift, sha256_helper_w15_shift, sha256_helper_w2_shift, sha256_helper_w3_shift, sha256_helper_w4_shift, sha256_helper_w5_shift, sha256_helper_w6_shift, sha256_helper_w7_shift, sha256_helper_w8_shift, sha256_helper_w9_shift, sha256_rounds_remaining_shift, sha256_sel_shift, sha256_start_shift -#define AVM2_TO_BE_SHIFTED(e) e.bc_decomposition_bytes, e.bc_decomposition_bytes_pc_plus_1, e.bc_decomposition_bytes_pc_plus_10, e.bc_decomposition_bytes_pc_plus_11, e.bc_decomposition_bytes_pc_plus_12, e.bc_decomposition_bytes_pc_plus_13, e.bc_decomposition_bytes_pc_plus_14, e.bc_decomposition_bytes_pc_plus_15, e.bc_decomposition_bytes_pc_plus_16, e.bc_decomposition_bytes_pc_plus_17, e.bc_decomposition_bytes_pc_plus_18, e.bc_decomposition_bytes_pc_plus_19, e.bc_decomposition_bytes_pc_plus_2, e.bc_decomposition_bytes_pc_plus_20, e.bc_decomposition_bytes_pc_plus_21, e.bc_decomposition_bytes_pc_plus_22, e.bc_decomposition_bytes_pc_plus_23, e.bc_decomposition_bytes_pc_plus_24, e.bc_decomposition_bytes_pc_plus_25, e.bc_decomposition_bytes_pc_plus_26, e.bc_decomposition_bytes_pc_plus_27, e.bc_decomposition_bytes_pc_plus_28, e.bc_decomposition_bytes_pc_plus_29, e.bc_decomposition_bytes_pc_plus_3, e.bc_decomposition_bytes_pc_plus_30, e.bc_decomposition_bytes_pc_plus_31, e.bc_decomposition_bytes_pc_plus_32, e.bc_decomposition_bytes_pc_plus_33, e.bc_decomposition_bytes_pc_plus_34, e.bc_decomposition_bytes_pc_plus_35, e.bc_decomposition_bytes_pc_plus_4, e.bc_decomposition_bytes_pc_plus_5, e.bc_decomposition_bytes_pc_plus_6, e.bc_decomposition_bytes_pc_plus_7, e.bc_decomposition_bytes_pc_plus_8, e.bc_decomposition_bytes_pc_plus_9, e.bc_decomposition_bytes_remaining, e.bc_decomposition_id, e.bc_decomposition_pc, e.bc_decomposition_sel, e.bc_hashing_bytecode_id, e.bc_hashing_incremental_hash, e.bc_hashing_pc_index, e.bc_hashing_sel, e.bc_hashing_start, e.bitwise_acc_ia, e.bitwise_acc_ib, e.bitwise_acc_ic, e.bitwise_ctr, e.bitwise_op_id, e.execution_sel, e.poseidon2_hash_a_0, e.poseidon2_hash_a_1, e.poseidon2_hash_a_2, e.poseidon2_hash_a_3, e.poseidon2_hash_input_0, e.poseidon2_hash_input_1, e.poseidon2_hash_input_2, e.poseidon2_hash_num_perm_rounds_rem, e.poseidon2_hash_output, e.poseidon2_hash_sel, e.poseidon2_hash_start, e.scalar_mul_bit_idx, e.scalar_mul_point_inf, e.scalar_mul_point_x, e.scalar_mul_point_y, e.scalar_mul_res_inf, e.scalar_mul_res_x, e.scalar_mul_res_y, e.scalar_mul_scalar, e.scalar_mul_sel, e.scalar_mul_start, e.scalar_mul_temp_inf, e.scalar_mul_temp_x, e.scalar_mul_temp_y, e.sha256_a, e.sha256_b, e.sha256_c, e.sha256_d, e.sha256_e, e.sha256_f, e.sha256_g, e.sha256_h, e.sha256_helper_w0, e.sha256_helper_w1, e.sha256_helper_w10, e.sha256_helper_w11, e.sha256_helper_w12, e.sha256_helper_w13, e.sha256_helper_w14, e.sha256_helper_w15, e.sha256_helper_w2, e.sha256_helper_w3, e.sha256_helper_w4, e.sha256_helper_w5, e.sha256_helper_w6, e.sha256_helper_w7, e.sha256_helper_w8, e.sha256_helper_w9, e.sha256_rounds_remaining, e.sha256_sel, e.sha256_start +#define AVM2_PRECOMPUTED_ENTITIES precomputed_as_unary, precomputed_bitwise_input_a, precomputed_bitwise_input_b, precomputed_bitwise_op_id, precomputed_bitwise_output, precomputed_clk, precomputed_exec_opcode, precomputed_first_row, precomputed_instr_size_in_bytes, precomputed_integral_tag_length, precomputed_p_decomposition_limb, precomputed_p_decomposition_limb_index, precomputed_p_decomposition_radix, precomputed_power_of_2, precomputed_sel_bitwise, precomputed_sel_integral_tag, precomputed_sel_op_dc_0, precomputed_sel_op_dc_1, precomputed_sel_op_dc_10, precomputed_sel_op_dc_11, precomputed_sel_op_dc_12, precomputed_sel_op_dc_13, precomputed_sel_op_dc_14, precomputed_sel_op_dc_15, precomputed_sel_op_dc_16, precomputed_sel_op_dc_17, precomputed_sel_op_dc_2, precomputed_sel_op_dc_3, precomputed_sel_op_dc_4, precomputed_sel_op_dc_5, precomputed_sel_op_dc_6, precomputed_sel_op_dc_7, precomputed_sel_op_dc_8, precomputed_sel_op_dc_9, precomputed_sel_p_decomposition, precomputed_sel_range_16, precomputed_sel_range_8, precomputed_sel_range_wire_opcode, precomputed_sel_sha256_compression, precomputed_sel_to_radix_safe_limbs, precomputed_sel_unary, precomputed_sha256_compression_round_constant, precomputed_to_radix_safe_limbs, precomputed_zero +#define AVM2_WIRE_ENTITIES execution_input, alu_dst_addr, alu_ia, alu_ia_addr, alu_ib, alu_ib_addr, alu_ic, alu_op, alu_sel_op_add, bc_decomposition_abs_diff, bc_decomposition_bytes, bc_decomposition_bytes_pc_plus_1, bc_decomposition_bytes_pc_plus_10, bc_decomposition_bytes_pc_plus_11, bc_decomposition_bytes_pc_plus_12, bc_decomposition_bytes_pc_plus_13, bc_decomposition_bytes_pc_plus_14, bc_decomposition_bytes_pc_plus_15, bc_decomposition_bytes_pc_plus_16, bc_decomposition_bytes_pc_plus_17, bc_decomposition_bytes_pc_plus_18, bc_decomposition_bytes_pc_plus_19, bc_decomposition_bytes_pc_plus_2, bc_decomposition_bytes_pc_plus_20, bc_decomposition_bytes_pc_plus_21, bc_decomposition_bytes_pc_plus_22, bc_decomposition_bytes_pc_plus_23, bc_decomposition_bytes_pc_plus_24, bc_decomposition_bytes_pc_plus_25, bc_decomposition_bytes_pc_plus_26, bc_decomposition_bytes_pc_plus_27, bc_decomposition_bytes_pc_plus_28, bc_decomposition_bytes_pc_plus_29, bc_decomposition_bytes_pc_plus_3, bc_decomposition_bytes_pc_plus_30, bc_decomposition_bytes_pc_plus_31, bc_decomposition_bytes_pc_plus_32, bc_decomposition_bytes_pc_plus_33, bc_decomposition_bytes_pc_plus_34, bc_decomposition_bytes_pc_plus_35, bc_decomposition_bytes_pc_plus_36, bc_decomposition_bytes_pc_plus_4, bc_decomposition_bytes_pc_plus_5, bc_decomposition_bytes_pc_plus_6, bc_decomposition_bytes_pc_plus_7, bc_decomposition_bytes_pc_plus_8, bc_decomposition_bytes_pc_plus_9, bc_decomposition_bytes_rem_inv, bc_decomposition_bytes_rem_min_one_inv, bc_decomposition_bytes_remaining, bc_decomposition_bytes_to_read, bc_decomposition_bytes_to_read_unary, bc_decomposition_id, bc_decomposition_last_of_contract, bc_decomposition_packed_field, bc_decomposition_pc, bc_decomposition_sel, bc_decomposition_sel_overflow_correction_needed, bc_decomposition_sel_packed, bc_decomposition_sel_pc_plus_1, bc_decomposition_sel_pc_plus_10, bc_decomposition_sel_pc_plus_11, bc_decomposition_sel_pc_plus_12, bc_decomposition_sel_pc_plus_13, bc_decomposition_sel_pc_plus_14, bc_decomposition_sel_pc_plus_15, bc_decomposition_sel_pc_plus_16, bc_decomposition_sel_pc_plus_17, bc_decomposition_sel_pc_plus_18, bc_decomposition_sel_pc_plus_19, bc_decomposition_sel_pc_plus_2, bc_decomposition_sel_pc_plus_20, bc_decomposition_sel_pc_plus_21, bc_decomposition_sel_pc_plus_22, bc_decomposition_sel_pc_plus_23, bc_decomposition_sel_pc_plus_24, bc_decomposition_sel_pc_plus_25, bc_decomposition_sel_pc_plus_26, bc_decomposition_sel_pc_plus_27, bc_decomposition_sel_pc_plus_28, bc_decomposition_sel_pc_plus_29, bc_decomposition_sel_pc_plus_3, bc_decomposition_sel_pc_plus_30, bc_decomposition_sel_pc_plus_31, bc_decomposition_sel_pc_plus_32, bc_decomposition_sel_pc_plus_33, bc_decomposition_sel_pc_plus_34, bc_decomposition_sel_pc_plus_35, bc_decomposition_sel_pc_plus_36, bc_decomposition_sel_pc_plus_4, bc_decomposition_sel_pc_plus_5, bc_decomposition_sel_pc_plus_6, bc_decomposition_sel_pc_plus_7, bc_decomposition_sel_pc_plus_8, bc_decomposition_sel_pc_plus_9, bc_hashing_bytecode_id, bc_hashing_incremental_hash, bc_hashing_latch, bc_hashing_output_hash, bc_hashing_packed_field, bc_hashing_pc_index, bc_hashing_sel, bc_hashing_start, bc_retrieval_address, bc_retrieval_artifact_hash, bc_retrieval_bytecode_id, bc_retrieval_class_id, bc_retrieval_deployer_addr, bc_retrieval_err, bc_retrieval_incoming_viewing_key_x, bc_retrieval_incoming_viewing_key_y, bc_retrieval_init_hash, bc_retrieval_nullifier_key_x, bc_retrieval_nullifier_key_y, bc_retrieval_outgoing_viewing_key_x, bc_retrieval_outgoing_viewing_key_y, bc_retrieval_private_function_root, bc_retrieval_public_bytecode_commitment, bc_retrieval_salt, bc_retrieval_sel, bc_retrieval_siloed_address, bc_retrieval_tagging_key_x, bc_retrieval_tagging_key_y, bitwise_acc_ia, bitwise_acc_ib, bitwise_acc_ic, bitwise_ctr, bitwise_ctr_inv, bitwise_ctr_min_one_inv, bitwise_ia_byte, bitwise_ib_byte, bitwise_ic_byte, bitwise_last, bitwise_op_id, bitwise_sel, bitwise_start, bitwise_tag, class_id_derivation_artifact_hash, class_id_derivation_class_id, class_id_derivation_private_function_root, class_id_derivation_public_bytecode_commitment, class_id_derivation_sel, class_id_derivation_temp_constant_for_lookup, ecc_add_op, ecc_double_op, ecc_inv_2_p_y, ecc_inv_x_diff, ecc_inv_y_diff, ecc_lambda, ecc_p_is_inf, ecc_p_x, ecc_p_y, ecc_q_is_inf, ecc_q_x, ecc_q_y, ecc_r_is_inf, ecc_r_x, ecc_r_y, ecc_result_infinity, ecc_sel, ecc_x_match, ecc_y_match, execution_addressing_error_idx, execution_addressing_error_kind, execution_base_address_tag, execution_base_address_val, execution_bytecode_id, execution_clk, execution_ex_opcode, execution_indirect, execution_last, execution_op1, execution_op1_after_relative, execution_op2, execution_op2_after_relative, execution_op3, execution_op3_after_relative, execution_op4, execution_op4_after_relative, execution_pc, execution_rop1, execution_rop2, execution_rop3, execution_rop4, execution_sel, execution_sel_addressing_error, execution_sel_op1_is_address, execution_sel_op2_is_address, execution_sel_op3_is_address, execution_sel_op4_is_address, instr_fetching_bd0, instr_fetching_bd1, instr_fetching_bd10, instr_fetching_bd11, instr_fetching_bd12, instr_fetching_bd13, instr_fetching_bd14, instr_fetching_bd15, instr_fetching_bd16, instr_fetching_bd17, instr_fetching_bd18, instr_fetching_bd19, instr_fetching_bd2, instr_fetching_bd20, instr_fetching_bd21, instr_fetching_bd22, instr_fetching_bd23, instr_fetching_bd24, instr_fetching_bd25, instr_fetching_bd26, instr_fetching_bd27, instr_fetching_bd28, instr_fetching_bd29, instr_fetching_bd3, instr_fetching_bd30, instr_fetching_bd31, instr_fetching_bd32, instr_fetching_bd33, instr_fetching_bd34, instr_fetching_bd35, instr_fetching_bd36, instr_fetching_bd4, instr_fetching_bd5, instr_fetching_bd6, instr_fetching_bd7, instr_fetching_bd8, instr_fetching_bd9, instr_fetching_bytecode_id, instr_fetching_exec_opcode, instr_fetching_indirect, instr_fetching_instr_size_in_bytes, instr_fetching_op1, instr_fetching_op2, instr_fetching_op3, instr_fetching_op4, instr_fetching_op5, instr_fetching_op6, instr_fetching_op7, instr_fetching_pc, instr_fetching_sel, instr_fetching_sel_op_dc_0, instr_fetching_sel_op_dc_1, instr_fetching_sel_op_dc_10, instr_fetching_sel_op_dc_11, instr_fetching_sel_op_dc_12, instr_fetching_sel_op_dc_13, instr_fetching_sel_op_dc_14, instr_fetching_sel_op_dc_15, instr_fetching_sel_op_dc_16, instr_fetching_sel_op_dc_17, instr_fetching_sel_op_dc_2, instr_fetching_sel_op_dc_3, instr_fetching_sel_op_dc_4, instr_fetching_sel_op_dc_5, instr_fetching_sel_op_dc_6, instr_fetching_sel_op_dc_7, instr_fetching_sel_op_dc_8, instr_fetching_sel_op_dc_9, poseidon2_hash_a_0, poseidon2_hash_a_1, poseidon2_hash_a_2, poseidon2_hash_a_3, poseidon2_hash_b_0, poseidon2_hash_b_1, poseidon2_hash_b_2, poseidon2_hash_b_3, poseidon2_hash_end, poseidon2_hash_input_0, poseidon2_hash_input_1, poseidon2_hash_input_2, poseidon2_hash_input_len, poseidon2_hash_num_perm_rounds_rem, poseidon2_hash_num_perm_rounds_rem_inv, poseidon2_hash_output, poseidon2_hash_padding, poseidon2_hash_sel, poseidon2_hash_start, poseidon2_perm_B_10_0, poseidon2_perm_B_10_1, poseidon2_perm_B_10_2, poseidon2_perm_B_10_3, poseidon2_perm_B_11_0, poseidon2_perm_B_11_1, poseidon2_perm_B_11_2, poseidon2_perm_B_11_3, poseidon2_perm_B_12_0, poseidon2_perm_B_12_1, poseidon2_perm_B_12_2, poseidon2_perm_B_12_3, poseidon2_perm_B_13_0, poseidon2_perm_B_13_1, poseidon2_perm_B_13_2, poseidon2_perm_B_13_3, poseidon2_perm_B_14_0, poseidon2_perm_B_14_1, poseidon2_perm_B_14_2, poseidon2_perm_B_14_3, poseidon2_perm_B_15_0, poseidon2_perm_B_15_1, poseidon2_perm_B_15_2, poseidon2_perm_B_15_3, poseidon2_perm_B_16_0, poseidon2_perm_B_16_1, poseidon2_perm_B_16_2, poseidon2_perm_B_16_3, poseidon2_perm_B_17_0, poseidon2_perm_B_17_1, poseidon2_perm_B_17_2, poseidon2_perm_B_17_3, poseidon2_perm_B_18_0, poseidon2_perm_B_18_1, poseidon2_perm_B_18_2, poseidon2_perm_B_18_3, poseidon2_perm_B_19_0, poseidon2_perm_B_19_1, poseidon2_perm_B_19_2, poseidon2_perm_B_19_3, poseidon2_perm_B_20_0, poseidon2_perm_B_20_1, poseidon2_perm_B_20_2, poseidon2_perm_B_20_3, poseidon2_perm_B_21_0, poseidon2_perm_B_21_1, poseidon2_perm_B_21_2, poseidon2_perm_B_21_3, poseidon2_perm_B_22_0, poseidon2_perm_B_22_1, poseidon2_perm_B_22_2, poseidon2_perm_B_22_3, poseidon2_perm_B_23_0, poseidon2_perm_B_23_1, poseidon2_perm_B_23_2, poseidon2_perm_B_23_3, poseidon2_perm_B_24_0, poseidon2_perm_B_24_1, poseidon2_perm_B_24_2, poseidon2_perm_B_24_3, poseidon2_perm_B_25_0, poseidon2_perm_B_25_1, poseidon2_perm_B_25_2, poseidon2_perm_B_25_3, poseidon2_perm_B_26_0, poseidon2_perm_B_26_1, poseidon2_perm_B_26_2, poseidon2_perm_B_26_3, poseidon2_perm_B_27_0, poseidon2_perm_B_27_1, poseidon2_perm_B_27_2, poseidon2_perm_B_27_3, poseidon2_perm_B_28_0, poseidon2_perm_B_28_1, poseidon2_perm_B_28_2, poseidon2_perm_B_28_3, poseidon2_perm_B_29_0, poseidon2_perm_B_29_1, poseidon2_perm_B_29_2, poseidon2_perm_B_29_3, poseidon2_perm_B_30_0, poseidon2_perm_B_30_1, poseidon2_perm_B_30_2, poseidon2_perm_B_30_3, poseidon2_perm_B_31_0, poseidon2_perm_B_31_1, poseidon2_perm_B_31_2, poseidon2_perm_B_31_3, poseidon2_perm_B_32_0, poseidon2_perm_B_32_1, poseidon2_perm_B_32_2, poseidon2_perm_B_32_3, poseidon2_perm_B_33_0, poseidon2_perm_B_33_1, poseidon2_perm_B_33_2, poseidon2_perm_B_33_3, poseidon2_perm_B_34_0, poseidon2_perm_B_34_1, poseidon2_perm_B_34_2, poseidon2_perm_B_34_3, poseidon2_perm_B_35_0, poseidon2_perm_B_35_1, poseidon2_perm_B_35_2, poseidon2_perm_B_35_3, poseidon2_perm_B_36_0, poseidon2_perm_B_36_1, poseidon2_perm_B_36_2, poseidon2_perm_B_36_3, poseidon2_perm_B_37_0, poseidon2_perm_B_37_1, poseidon2_perm_B_37_2, poseidon2_perm_B_37_3, poseidon2_perm_B_38_0, poseidon2_perm_B_38_1, poseidon2_perm_B_38_2, poseidon2_perm_B_38_3, poseidon2_perm_B_39_0, poseidon2_perm_B_39_1, poseidon2_perm_B_39_2, poseidon2_perm_B_39_3, poseidon2_perm_B_40_0, poseidon2_perm_B_40_1, poseidon2_perm_B_40_2, poseidon2_perm_B_40_3, poseidon2_perm_B_41_0, poseidon2_perm_B_41_1, poseidon2_perm_B_41_2, poseidon2_perm_B_41_3, poseidon2_perm_B_42_0, poseidon2_perm_B_42_1, poseidon2_perm_B_42_2, poseidon2_perm_B_42_3, poseidon2_perm_B_43_0, poseidon2_perm_B_43_1, poseidon2_perm_B_43_2, poseidon2_perm_B_43_3, poseidon2_perm_B_44_0, poseidon2_perm_B_44_1, poseidon2_perm_B_44_2, poseidon2_perm_B_44_3, poseidon2_perm_B_45_0, poseidon2_perm_B_45_1, poseidon2_perm_B_45_2, poseidon2_perm_B_45_3, poseidon2_perm_B_46_0, poseidon2_perm_B_46_1, poseidon2_perm_B_46_2, poseidon2_perm_B_46_3, poseidon2_perm_B_47_0, poseidon2_perm_B_47_1, poseidon2_perm_B_47_2, poseidon2_perm_B_47_3, poseidon2_perm_B_48_0, poseidon2_perm_B_48_1, poseidon2_perm_B_48_2, poseidon2_perm_B_48_3, poseidon2_perm_B_49_0, poseidon2_perm_B_49_1, poseidon2_perm_B_49_2, poseidon2_perm_B_49_3, poseidon2_perm_B_4_0, poseidon2_perm_B_4_1, poseidon2_perm_B_4_2, poseidon2_perm_B_4_3, poseidon2_perm_B_50_0, poseidon2_perm_B_50_1, poseidon2_perm_B_50_2, poseidon2_perm_B_50_3, poseidon2_perm_B_51_0, poseidon2_perm_B_51_1, poseidon2_perm_B_51_2, poseidon2_perm_B_51_3, poseidon2_perm_B_52_0, poseidon2_perm_B_52_1, poseidon2_perm_B_52_2, poseidon2_perm_B_52_3, poseidon2_perm_B_53_0, poseidon2_perm_B_53_1, poseidon2_perm_B_53_2, poseidon2_perm_B_53_3, poseidon2_perm_B_54_0, poseidon2_perm_B_54_1, poseidon2_perm_B_54_2, poseidon2_perm_B_54_3, poseidon2_perm_B_55_0, poseidon2_perm_B_55_1, poseidon2_perm_B_55_2, poseidon2_perm_B_55_3, poseidon2_perm_B_56_0, poseidon2_perm_B_56_1, poseidon2_perm_B_56_2, poseidon2_perm_B_56_3, poseidon2_perm_B_57_0, poseidon2_perm_B_57_1, poseidon2_perm_B_57_2, poseidon2_perm_B_57_3, poseidon2_perm_B_58_0, poseidon2_perm_B_58_1, poseidon2_perm_B_58_2, poseidon2_perm_B_58_3, poseidon2_perm_B_59_0, poseidon2_perm_B_59_1, poseidon2_perm_B_59_2, poseidon2_perm_B_59_3, poseidon2_perm_B_5_0, poseidon2_perm_B_5_1, poseidon2_perm_B_5_2, poseidon2_perm_B_5_3, poseidon2_perm_B_6_0, poseidon2_perm_B_6_1, poseidon2_perm_B_6_2, poseidon2_perm_B_6_3, poseidon2_perm_B_7_0, poseidon2_perm_B_7_1, poseidon2_perm_B_7_2, poseidon2_perm_B_7_3, poseidon2_perm_B_8_0, poseidon2_perm_B_8_1, poseidon2_perm_B_8_2, poseidon2_perm_B_8_3, poseidon2_perm_B_9_0, poseidon2_perm_B_9_1, poseidon2_perm_B_9_2, poseidon2_perm_B_9_3, poseidon2_perm_EXT_LAYER_4, poseidon2_perm_EXT_LAYER_5, poseidon2_perm_EXT_LAYER_6, poseidon2_perm_EXT_LAYER_7, poseidon2_perm_T_0_4, poseidon2_perm_T_0_5, poseidon2_perm_T_0_6, poseidon2_perm_T_0_7, poseidon2_perm_T_1_4, poseidon2_perm_T_1_5, poseidon2_perm_T_1_6, poseidon2_perm_T_1_7, poseidon2_perm_T_2_4, poseidon2_perm_T_2_5, poseidon2_perm_T_2_6, poseidon2_perm_T_2_7, poseidon2_perm_T_3_4, poseidon2_perm_T_3_5, poseidon2_perm_T_3_6, poseidon2_perm_T_3_7, poseidon2_perm_T_60_4, poseidon2_perm_T_60_5, poseidon2_perm_T_60_6, poseidon2_perm_T_60_7, poseidon2_perm_T_61_4, poseidon2_perm_T_61_5, poseidon2_perm_T_61_6, poseidon2_perm_T_61_7, poseidon2_perm_T_62_4, poseidon2_perm_T_62_5, poseidon2_perm_T_62_6, poseidon2_perm_T_62_7, poseidon2_perm_T_63_4, poseidon2_perm_T_63_5, poseidon2_perm_T_63_6, poseidon2_perm_T_63_7, poseidon2_perm_a_0, poseidon2_perm_a_1, poseidon2_perm_a_2, poseidon2_perm_a_3, poseidon2_perm_b_0, poseidon2_perm_b_1, poseidon2_perm_b_2, poseidon2_perm_b_3, poseidon2_perm_sel, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_rng_chk_bits, range_check_sel, range_check_sel_r0_16_bit_rng_lookup, range_check_sel_r1_16_bit_rng_lookup, range_check_sel_r2_16_bit_rng_lookup, range_check_sel_r3_16_bit_rng_lookup, range_check_sel_r4_16_bit_rng_lookup, range_check_sel_r5_16_bit_rng_lookup, range_check_sel_r6_16_bit_rng_lookup, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, scalar_mul_bit, scalar_mul_bit_idx, scalar_mul_bit_radix, scalar_mul_end, scalar_mul_not_end, scalar_mul_point_inf, scalar_mul_point_x, scalar_mul_point_y, scalar_mul_res_inf, scalar_mul_res_x, scalar_mul_res_y, scalar_mul_scalar, scalar_mul_sel, scalar_mul_should_add, scalar_mul_start, scalar_mul_temp_inf, scalar_mul_temp_x, scalar_mul_temp_y, sha256_a, sha256_a_and_b, sha256_a_and_b_xor_a_and_c, sha256_a_and_c, sha256_a_rotr_13, sha256_a_rotr_2, sha256_a_rotr_22, sha256_a_rotr_2_xor_a_rotr_13, sha256_and_sel, sha256_b, sha256_b_and_c, sha256_c, sha256_ch, sha256_clk, sha256_computed_w_lhs, sha256_computed_w_rhs, sha256_d, sha256_e, sha256_e_and_f, sha256_e_rotr_11, sha256_e_rotr_25, sha256_e_rotr_6, sha256_e_rotr_6_xor_e_rotr_11, sha256_f, sha256_g, sha256_h, sha256_helper_w0, sha256_helper_w1, sha256_helper_w10, sha256_helper_w11, sha256_helper_w12, sha256_helper_w13, sha256_helper_w14, sha256_helper_w15, sha256_helper_w2, sha256_helper_w3, sha256_helper_w4, sha256_helper_w5, sha256_helper_w6, sha256_helper_w7, sha256_helper_w8, sha256_helper_w9, sha256_init_a, sha256_init_b, sha256_init_c, sha256_init_d, sha256_init_e, sha256_init_f, sha256_init_g, sha256_init_h, sha256_input_offset, sha256_is_input_round, sha256_latch, sha256_lhs_a_13, sha256_lhs_a_2, sha256_lhs_a_22, sha256_lhs_e_11, sha256_lhs_e_25, sha256_lhs_e_6, sha256_lhs_w_10, sha256_lhs_w_17, sha256_lhs_w_18, sha256_lhs_w_19, sha256_lhs_w_3, sha256_lhs_w_7, sha256_maj, sha256_next_a_lhs, sha256_next_a_rhs, sha256_next_e_lhs, sha256_next_e_rhs, sha256_not_e, sha256_not_e_and_g, sha256_output_a_lhs, sha256_output_a_rhs, sha256_output_b_lhs, sha256_output_b_rhs, sha256_output_c_lhs, sha256_output_c_rhs, sha256_output_d_lhs, sha256_output_d_rhs, sha256_output_e_lhs, sha256_output_e_rhs, sha256_output_f_lhs, sha256_output_f_rhs, sha256_output_g_lhs, sha256_output_g_rhs, sha256_output_h_lhs, sha256_output_h_rhs, sha256_output_offset, sha256_perform_round, sha256_rhs_a_13, sha256_rhs_a_2, sha256_rhs_a_22, sha256_rhs_e_11, sha256_rhs_e_25, sha256_rhs_e_6, sha256_rhs_w_10, sha256_rhs_w_17, sha256_rhs_w_18, sha256_rhs_w_19, sha256_rhs_w_3, sha256_rhs_w_7, sha256_round_constant, sha256_round_count, sha256_rounds_remaining, sha256_rounds_remaining_inv, sha256_s_0, sha256_s_1, sha256_sel, sha256_start, sha256_state_offset, sha256_w, sha256_w_15_rotr_18, sha256_w_15_rotr_7, sha256_w_15_rotr_7_xor_w_15_rotr_18, sha256_w_15_rshift_3, sha256_w_2_rotr_17, sha256_w_2_rotr_17_xor_w_2_rotr_19, sha256_w_2_rotr_19, sha256_w_2_rshift_10, sha256_w_s_0, sha256_w_s_1, sha256_xor_sel, to_radix_acc, to_radix_acc_under_p, to_radix_end, to_radix_exponent, to_radix_found, to_radix_is_unsafe_limb, to_radix_limb, to_radix_limb_eq_p, to_radix_limb_index, to_radix_limb_lt_p, to_radix_limb_p_diff, to_radix_limb_radix_diff, to_radix_not_end, to_radix_not_padding_limb, to_radix_p_limb, to_radix_radix, to_radix_rem_inverse, to_radix_safe_limbs, to_radix_safety_diff_inverse, to_radix_sel, to_radix_start, to_radix_value, lookup_bc_decomposition_bytes_are_bytes_counts, lookup_bc_decomposition_abs_diff_is_u16_counts, lookup_bc_decomposition_bytes_to_read_as_unary_counts, lookup_poseidon2_hash_poseidon2_perm_counts, lookup_bc_hashing_get_packed_field_counts, lookup_bc_hashing_iv_is_len_counts, lookup_bc_hashing_poseidon2_hash_counts, lookup_bc_retrieval_class_id_derivation_counts, lookup_bc_retrieval_bytecode_hash_is_correct_counts, lookup_instr_fetching_bytes_from_bc_dec_counts, lookup_instr_fetching_wire_instruction_info_counts, lookup_class_id_derivation_class_id_poseidon2_0_counts, lookup_class_id_derivation_class_id_poseidon2_1_counts, lookup_range_check_dyn_rng_chk_pow_2_counts, lookup_range_check_dyn_diff_is_u16_counts, lookup_range_check_r0_is_u16_counts, lookup_range_check_r1_is_u16_counts, lookup_range_check_r2_is_u16_counts, lookup_range_check_r3_is_u16_counts, lookup_range_check_r4_is_u16_counts, lookup_range_check_r5_is_u16_counts, lookup_range_check_r6_is_u16_counts, lookup_range_check_r7_is_u16_counts, lookup_bitwise_integral_tag_length_counts, lookup_bitwise_byte_operations_counts, lookup_sha256_round_constant_counts, lookup_to_radix_limb_range_counts, lookup_to_radix_limb_less_than_radix_range_counts, lookup_to_radix_fetch_safe_limbs_counts, lookup_to_radix_fetch_p_limb_counts, lookup_to_radix_limb_p_diff_range_counts, lookup_scalar_mul_to_radix_counts, lookup_scalar_mul_double_counts, lookup_scalar_mul_add_counts +#define AVM2_DERIVED_WITNESS_ENTITIES lookup_bc_decomposition_bytes_are_bytes_inv, lookup_bc_decomposition_abs_diff_is_u16_inv, lookup_bc_decomposition_bytes_to_read_as_unary_inv, lookup_poseidon2_hash_poseidon2_perm_inv, lookup_bc_hashing_get_packed_field_inv, lookup_bc_hashing_iv_is_len_inv, lookup_bc_hashing_poseidon2_hash_inv, lookup_bc_retrieval_class_id_derivation_inv, lookup_bc_retrieval_bytecode_hash_is_correct_inv, lookup_instr_fetching_bytes_from_bc_dec_inv, lookup_instr_fetching_wire_instruction_info_inv, lookup_class_id_derivation_class_id_poseidon2_0_inv, lookup_class_id_derivation_class_id_poseidon2_1_inv, lookup_range_check_dyn_rng_chk_pow_2_inv, lookup_range_check_dyn_diff_is_u16_inv, lookup_range_check_r0_is_u16_inv, lookup_range_check_r1_is_u16_inv, lookup_range_check_r2_is_u16_inv, lookup_range_check_r3_is_u16_inv, lookup_range_check_r4_is_u16_inv, lookup_range_check_r5_is_u16_inv, lookup_range_check_r6_is_u16_inv, lookup_range_check_r7_is_u16_inv, lookup_bitwise_integral_tag_length_inv, lookup_bitwise_byte_operations_inv, lookup_sha256_round_constant_inv, lookup_to_radix_limb_range_inv, lookup_to_radix_limb_less_than_radix_range_inv, lookup_to_radix_fetch_safe_limbs_inv, lookup_to_radix_fetch_p_limb_inv, lookup_to_radix_limb_p_diff_range_inv, lookup_scalar_mul_to_radix_inv, lookup_scalar_mul_double_inv, lookup_scalar_mul_add_inv +#define AVM2_SHIFTED_ENTITIES bc_decomposition_bytes_shift, bc_decomposition_bytes_pc_plus_1_shift, bc_decomposition_bytes_pc_plus_10_shift, bc_decomposition_bytes_pc_plus_11_shift, bc_decomposition_bytes_pc_plus_12_shift, bc_decomposition_bytes_pc_plus_13_shift, bc_decomposition_bytes_pc_plus_14_shift, bc_decomposition_bytes_pc_plus_15_shift, bc_decomposition_bytes_pc_plus_16_shift, bc_decomposition_bytes_pc_plus_17_shift, bc_decomposition_bytes_pc_plus_18_shift, bc_decomposition_bytes_pc_plus_19_shift, bc_decomposition_bytes_pc_plus_2_shift, bc_decomposition_bytes_pc_plus_20_shift, bc_decomposition_bytes_pc_plus_21_shift, bc_decomposition_bytes_pc_plus_22_shift, bc_decomposition_bytes_pc_plus_23_shift, bc_decomposition_bytes_pc_plus_24_shift, bc_decomposition_bytes_pc_plus_25_shift, bc_decomposition_bytes_pc_plus_26_shift, bc_decomposition_bytes_pc_plus_27_shift, bc_decomposition_bytes_pc_plus_28_shift, bc_decomposition_bytes_pc_plus_29_shift, bc_decomposition_bytes_pc_plus_3_shift, bc_decomposition_bytes_pc_plus_30_shift, bc_decomposition_bytes_pc_plus_31_shift, bc_decomposition_bytes_pc_plus_32_shift, bc_decomposition_bytes_pc_plus_33_shift, bc_decomposition_bytes_pc_plus_34_shift, bc_decomposition_bytes_pc_plus_35_shift, bc_decomposition_bytes_pc_plus_4_shift, bc_decomposition_bytes_pc_plus_5_shift, bc_decomposition_bytes_pc_plus_6_shift, bc_decomposition_bytes_pc_plus_7_shift, bc_decomposition_bytes_pc_plus_8_shift, bc_decomposition_bytes_pc_plus_9_shift, bc_decomposition_bytes_remaining_shift, bc_decomposition_id_shift, bc_decomposition_pc_shift, bc_decomposition_sel_shift, bc_hashing_bytecode_id_shift, bc_hashing_incremental_hash_shift, bc_hashing_pc_index_shift, bc_hashing_sel_shift, bc_hashing_start_shift, bitwise_acc_ia_shift, bitwise_acc_ib_shift, bitwise_acc_ic_shift, bitwise_ctr_shift, bitwise_op_id_shift, execution_sel_shift, poseidon2_hash_a_0_shift, poseidon2_hash_a_1_shift, poseidon2_hash_a_2_shift, poseidon2_hash_a_3_shift, poseidon2_hash_input_0_shift, poseidon2_hash_input_1_shift, poseidon2_hash_input_2_shift, poseidon2_hash_num_perm_rounds_rem_shift, poseidon2_hash_output_shift, poseidon2_hash_sel_shift, poseidon2_hash_start_shift, scalar_mul_bit_idx_shift, scalar_mul_point_inf_shift, scalar_mul_point_x_shift, scalar_mul_point_y_shift, scalar_mul_res_inf_shift, scalar_mul_res_x_shift, scalar_mul_res_y_shift, scalar_mul_scalar_shift, scalar_mul_sel_shift, scalar_mul_start_shift, scalar_mul_temp_inf_shift, scalar_mul_temp_x_shift, scalar_mul_temp_y_shift, sha256_a_shift, sha256_b_shift, sha256_c_shift, sha256_d_shift, sha256_e_shift, sha256_f_shift, sha256_g_shift, sha256_h_shift, sha256_helper_w0_shift, sha256_helper_w1_shift, sha256_helper_w10_shift, sha256_helper_w11_shift, sha256_helper_w12_shift, sha256_helper_w13_shift, sha256_helper_w14_shift, sha256_helper_w15_shift, sha256_helper_w2_shift, sha256_helper_w3_shift, sha256_helper_w4_shift, sha256_helper_w5_shift, sha256_helper_w6_shift, sha256_helper_w7_shift, sha256_helper_w8_shift, sha256_helper_w9_shift, sha256_rounds_remaining_shift, sha256_sel_shift, sha256_start_shift, to_radix_acc_shift, to_radix_acc_under_p_shift, to_radix_exponent_shift, to_radix_limb_shift, to_radix_limb_eq_p_shift, to_radix_limb_index_shift, to_radix_limb_lt_p_shift, to_radix_not_padding_limb_shift, to_radix_radix_shift, to_radix_safe_limbs_shift, to_radix_sel_shift, to_radix_start_shift, to_radix_value_shift +#define AVM2_TO_BE_SHIFTED(e) e.bc_decomposition_bytes, e.bc_decomposition_bytes_pc_plus_1, e.bc_decomposition_bytes_pc_plus_10, e.bc_decomposition_bytes_pc_plus_11, e.bc_decomposition_bytes_pc_plus_12, e.bc_decomposition_bytes_pc_plus_13, e.bc_decomposition_bytes_pc_plus_14, e.bc_decomposition_bytes_pc_plus_15, e.bc_decomposition_bytes_pc_plus_16, e.bc_decomposition_bytes_pc_plus_17, e.bc_decomposition_bytes_pc_plus_18, e.bc_decomposition_bytes_pc_plus_19, e.bc_decomposition_bytes_pc_plus_2, e.bc_decomposition_bytes_pc_plus_20, e.bc_decomposition_bytes_pc_plus_21, e.bc_decomposition_bytes_pc_plus_22, e.bc_decomposition_bytes_pc_plus_23, e.bc_decomposition_bytes_pc_plus_24, e.bc_decomposition_bytes_pc_plus_25, e.bc_decomposition_bytes_pc_plus_26, e.bc_decomposition_bytes_pc_plus_27, e.bc_decomposition_bytes_pc_plus_28, e.bc_decomposition_bytes_pc_plus_29, e.bc_decomposition_bytes_pc_plus_3, e.bc_decomposition_bytes_pc_plus_30, e.bc_decomposition_bytes_pc_plus_31, e.bc_decomposition_bytes_pc_plus_32, e.bc_decomposition_bytes_pc_plus_33, e.bc_decomposition_bytes_pc_plus_34, e.bc_decomposition_bytes_pc_plus_35, e.bc_decomposition_bytes_pc_plus_4, e.bc_decomposition_bytes_pc_plus_5, e.bc_decomposition_bytes_pc_plus_6, e.bc_decomposition_bytes_pc_plus_7, e.bc_decomposition_bytes_pc_plus_8, e.bc_decomposition_bytes_pc_plus_9, e.bc_decomposition_bytes_remaining, e.bc_decomposition_id, e.bc_decomposition_pc, e.bc_decomposition_sel, e.bc_hashing_bytecode_id, e.bc_hashing_incremental_hash, e.bc_hashing_pc_index, e.bc_hashing_sel, e.bc_hashing_start, e.bitwise_acc_ia, e.bitwise_acc_ib, e.bitwise_acc_ic, e.bitwise_ctr, e.bitwise_op_id, e.execution_sel, e.poseidon2_hash_a_0, e.poseidon2_hash_a_1, e.poseidon2_hash_a_2, e.poseidon2_hash_a_3, e.poseidon2_hash_input_0, e.poseidon2_hash_input_1, e.poseidon2_hash_input_2, e.poseidon2_hash_num_perm_rounds_rem, e.poseidon2_hash_output, e.poseidon2_hash_sel, e.poseidon2_hash_start, e.scalar_mul_bit_idx, e.scalar_mul_point_inf, e.scalar_mul_point_x, e.scalar_mul_point_y, e.scalar_mul_res_inf, e.scalar_mul_res_x, e.scalar_mul_res_y, e.scalar_mul_scalar, e.scalar_mul_sel, e.scalar_mul_start, e.scalar_mul_temp_inf, e.scalar_mul_temp_x, e.scalar_mul_temp_y, e.sha256_a, e.sha256_b, e.sha256_c, e.sha256_d, e.sha256_e, e.sha256_f, e.sha256_g, e.sha256_h, e.sha256_helper_w0, e.sha256_helper_w1, e.sha256_helper_w10, e.sha256_helper_w11, e.sha256_helper_w12, e.sha256_helper_w13, e.sha256_helper_w14, e.sha256_helper_w15, e.sha256_helper_w2, e.sha256_helper_w3, e.sha256_helper_w4, e.sha256_helper_w5, e.sha256_helper_w6, e.sha256_helper_w7, e.sha256_helper_w8, e.sha256_helper_w9, e.sha256_rounds_remaining, e.sha256_sel, e.sha256_start, e.to_radix_acc, e.to_radix_acc_under_p, e.to_radix_exponent, e.to_radix_limb, e.to_radix_limb_eq_p, e.to_radix_limb_index, e.to_radix_limb_lt_p, e.to_radix_not_padding_limb, e.to_radix_radix, e.to_radix_safe_limbs, e.to_radix_sel, e.to_radix_start, e.to_radix_value #define AVM2_ALL_ENTITIES AVM2_PRECOMPUTED_ENTITIES, AVM2_WIRE_ENTITIES, AVM2_DERIVED_WITNESS_ENTITIES, AVM2_SHIFTED_ENTITIES #define AVM2_UNSHIFTED_ENTITIES AVM2_PRECOMPUTED_ENTITIES, AVM2_WIRE_ENTITIES, AVM2_DERIVED_WITNESS_ENTITIES #define AVM2_WITNESS_ENTITIES AVM2_WIRE_ENTITIES, AVM2_DERIVED_WITNESS_ENTITIES -#define AVM2_TO_BE_SHIFTED_COLUMNS Column::bc_decomposition_bytes, Column::bc_decomposition_bytes_pc_plus_1, Column::bc_decomposition_bytes_pc_plus_10, Column::bc_decomposition_bytes_pc_plus_11, Column::bc_decomposition_bytes_pc_plus_12, Column::bc_decomposition_bytes_pc_plus_13, Column::bc_decomposition_bytes_pc_plus_14, Column::bc_decomposition_bytes_pc_plus_15, Column::bc_decomposition_bytes_pc_plus_16, Column::bc_decomposition_bytes_pc_plus_17, Column::bc_decomposition_bytes_pc_plus_18, Column::bc_decomposition_bytes_pc_plus_19, Column::bc_decomposition_bytes_pc_plus_2, Column::bc_decomposition_bytes_pc_plus_20, Column::bc_decomposition_bytes_pc_plus_21, Column::bc_decomposition_bytes_pc_plus_22, Column::bc_decomposition_bytes_pc_plus_23, Column::bc_decomposition_bytes_pc_plus_24, Column::bc_decomposition_bytes_pc_plus_25, Column::bc_decomposition_bytes_pc_plus_26, Column::bc_decomposition_bytes_pc_plus_27, Column::bc_decomposition_bytes_pc_plus_28, Column::bc_decomposition_bytes_pc_plus_29, Column::bc_decomposition_bytes_pc_plus_3, Column::bc_decomposition_bytes_pc_plus_30, Column::bc_decomposition_bytes_pc_plus_31, Column::bc_decomposition_bytes_pc_plus_32, Column::bc_decomposition_bytes_pc_plus_33, Column::bc_decomposition_bytes_pc_plus_34, Column::bc_decomposition_bytes_pc_plus_35, Column::bc_decomposition_bytes_pc_plus_4, Column::bc_decomposition_bytes_pc_plus_5, Column::bc_decomposition_bytes_pc_plus_6, Column::bc_decomposition_bytes_pc_plus_7, Column::bc_decomposition_bytes_pc_plus_8, Column::bc_decomposition_bytes_pc_plus_9, Column::bc_decomposition_bytes_remaining, Column::bc_decomposition_id, Column::bc_decomposition_pc, Column::bc_decomposition_sel, Column::bc_hashing_bytecode_id, Column::bc_hashing_incremental_hash, Column::bc_hashing_pc_index, Column::bc_hashing_sel, Column::bc_hashing_start, Column::bitwise_acc_ia, Column::bitwise_acc_ib, Column::bitwise_acc_ic, Column::bitwise_ctr, Column::bitwise_op_id, Column::execution_sel, Column::poseidon2_hash_a_0, Column::poseidon2_hash_a_1, Column::poseidon2_hash_a_2, Column::poseidon2_hash_a_3, Column::poseidon2_hash_input_0, Column::poseidon2_hash_input_1, Column::poseidon2_hash_input_2, Column::poseidon2_hash_num_perm_rounds_rem, Column::poseidon2_hash_output, Column::poseidon2_hash_sel, Column::poseidon2_hash_start, Column::scalar_mul_bit_idx, Column::scalar_mul_point_inf, Column::scalar_mul_point_x, Column::scalar_mul_point_y, Column::scalar_mul_res_inf, Column::scalar_mul_res_x, Column::scalar_mul_res_y, Column::scalar_mul_scalar, Column::scalar_mul_sel, Column::scalar_mul_start, Column::scalar_mul_temp_inf, Column::scalar_mul_temp_x, Column::scalar_mul_temp_y, Column::sha256_a, Column::sha256_b, Column::sha256_c, Column::sha256_d, Column::sha256_e, Column::sha256_f, Column::sha256_g, Column::sha256_h, Column::sha256_helper_w0, Column::sha256_helper_w1, Column::sha256_helper_w10, Column::sha256_helper_w11, Column::sha256_helper_w12, Column::sha256_helper_w13, Column::sha256_helper_w14, Column::sha256_helper_w15, Column::sha256_helper_w2, Column::sha256_helper_w3, Column::sha256_helper_w4, Column::sha256_helper_w5, Column::sha256_helper_w6, Column::sha256_helper_w7, Column::sha256_helper_w8, Column::sha256_helper_w9, Column::sha256_rounds_remaining, Column::sha256_sel, Column::sha256_start -#define AVM2_SHIFTED_COLUMNS ColumnAndShifts::bc_decomposition_bytes_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_1_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_10_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_11_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_12_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_13_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_14_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_15_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_16_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_17_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_18_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_19_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_2_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_20_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_21_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_22_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_23_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_24_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_25_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_26_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_27_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_28_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_29_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_3_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_30_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_31_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_32_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_33_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_34_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_35_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_4_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_5_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_6_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_7_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_8_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_9_shift, ColumnAndShifts::bc_decomposition_bytes_remaining_shift, ColumnAndShifts::bc_decomposition_id_shift, ColumnAndShifts::bc_decomposition_pc_shift, ColumnAndShifts::bc_decomposition_sel_shift, ColumnAndShifts::bc_hashing_bytecode_id_shift, ColumnAndShifts::bc_hashing_incremental_hash_shift, ColumnAndShifts::bc_hashing_pc_index_shift, ColumnAndShifts::bc_hashing_sel_shift, ColumnAndShifts::bc_hashing_start_shift, ColumnAndShifts::bitwise_acc_ia_shift, ColumnAndShifts::bitwise_acc_ib_shift, ColumnAndShifts::bitwise_acc_ic_shift, ColumnAndShifts::bitwise_ctr_shift, ColumnAndShifts::bitwise_op_id_shift, ColumnAndShifts::execution_sel_shift, ColumnAndShifts::poseidon2_hash_a_0_shift, ColumnAndShifts::poseidon2_hash_a_1_shift, ColumnAndShifts::poseidon2_hash_a_2_shift, ColumnAndShifts::poseidon2_hash_a_3_shift, ColumnAndShifts::poseidon2_hash_input_0_shift, ColumnAndShifts::poseidon2_hash_input_1_shift, ColumnAndShifts::poseidon2_hash_input_2_shift, ColumnAndShifts::poseidon2_hash_num_perm_rounds_rem_shift, ColumnAndShifts::poseidon2_hash_output_shift, ColumnAndShifts::poseidon2_hash_sel_shift, ColumnAndShifts::poseidon2_hash_start_shift, ColumnAndShifts::scalar_mul_bit_idx_shift, ColumnAndShifts::scalar_mul_point_inf_shift, ColumnAndShifts::scalar_mul_point_x_shift, ColumnAndShifts::scalar_mul_point_y_shift, ColumnAndShifts::scalar_mul_res_inf_shift, ColumnAndShifts::scalar_mul_res_x_shift, ColumnAndShifts::scalar_mul_res_y_shift, ColumnAndShifts::scalar_mul_scalar_shift, ColumnAndShifts::scalar_mul_sel_shift, ColumnAndShifts::scalar_mul_start_shift, ColumnAndShifts::scalar_mul_temp_inf_shift, ColumnAndShifts::scalar_mul_temp_x_shift, ColumnAndShifts::scalar_mul_temp_y_shift, ColumnAndShifts::sha256_a_shift, ColumnAndShifts::sha256_b_shift, ColumnAndShifts::sha256_c_shift, ColumnAndShifts::sha256_d_shift, ColumnAndShifts::sha256_e_shift, ColumnAndShifts::sha256_f_shift, ColumnAndShifts::sha256_g_shift, ColumnAndShifts::sha256_h_shift, ColumnAndShifts::sha256_helper_w0_shift, ColumnAndShifts::sha256_helper_w1_shift, ColumnAndShifts::sha256_helper_w10_shift, ColumnAndShifts::sha256_helper_w11_shift, ColumnAndShifts::sha256_helper_w12_shift, ColumnAndShifts::sha256_helper_w13_shift, ColumnAndShifts::sha256_helper_w14_shift, ColumnAndShifts::sha256_helper_w15_shift, ColumnAndShifts::sha256_helper_w2_shift, ColumnAndShifts::sha256_helper_w3_shift, ColumnAndShifts::sha256_helper_w4_shift, ColumnAndShifts::sha256_helper_w5_shift, ColumnAndShifts::sha256_helper_w6_shift, ColumnAndShifts::sha256_helper_w7_shift, ColumnAndShifts::sha256_helper_w8_shift, ColumnAndShifts::sha256_helper_w9_shift, ColumnAndShifts::sha256_rounds_remaining_shift, ColumnAndShifts::sha256_sel_shift, ColumnAndShifts::sha256_start_shift +#define AVM2_TO_BE_SHIFTED_COLUMNS Column::bc_decomposition_bytes, Column::bc_decomposition_bytes_pc_plus_1, Column::bc_decomposition_bytes_pc_plus_10, Column::bc_decomposition_bytes_pc_plus_11, Column::bc_decomposition_bytes_pc_plus_12, Column::bc_decomposition_bytes_pc_plus_13, Column::bc_decomposition_bytes_pc_plus_14, Column::bc_decomposition_bytes_pc_plus_15, Column::bc_decomposition_bytes_pc_plus_16, Column::bc_decomposition_bytes_pc_plus_17, Column::bc_decomposition_bytes_pc_plus_18, Column::bc_decomposition_bytes_pc_plus_19, Column::bc_decomposition_bytes_pc_plus_2, Column::bc_decomposition_bytes_pc_plus_20, Column::bc_decomposition_bytes_pc_plus_21, Column::bc_decomposition_bytes_pc_plus_22, Column::bc_decomposition_bytes_pc_plus_23, Column::bc_decomposition_bytes_pc_plus_24, Column::bc_decomposition_bytes_pc_plus_25, Column::bc_decomposition_bytes_pc_plus_26, Column::bc_decomposition_bytes_pc_plus_27, Column::bc_decomposition_bytes_pc_plus_28, Column::bc_decomposition_bytes_pc_plus_29, Column::bc_decomposition_bytes_pc_plus_3, Column::bc_decomposition_bytes_pc_plus_30, Column::bc_decomposition_bytes_pc_plus_31, Column::bc_decomposition_bytes_pc_plus_32, Column::bc_decomposition_bytes_pc_plus_33, Column::bc_decomposition_bytes_pc_plus_34, Column::bc_decomposition_bytes_pc_plus_35, Column::bc_decomposition_bytes_pc_plus_4, Column::bc_decomposition_bytes_pc_plus_5, Column::bc_decomposition_bytes_pc_plus_6, Column::bc_decomposition_bytes_pc_plus_7, Column::bc_decomposition_bytes_pc_plus_8, Column::bc_decomposition_bytes_pc_plus_9, Column::bc_decomposition_bytes_remaining, Column::bc_decomposition_id, Column::bc_decomposition_pc, Column::bc_decomposition_sel, Column::bc_hashing_bytecode_id, Column::bc_hashing_incremental_hash, Column::bc_hashing_pc_index, Column::bc_hashing_sel, Column::bc_hashing_start, Column::bitwise_acc_ia, Column::bitwise_acc_ib, Column::bitwise_acc_ic, Column::bitwise_ctr, Column::bitwise_op_id, Column::execution_sel, Column::poseidon2_hash_a_0, Column::poseidon2_hash_a_1, Column::poseidon2_hash_a_2, Column::poseidon2_hash_a_3, Column::poseidon2_hash_input_0, Column::poseidon2_hash_input_1, Column::poseidon2_hash_input_2, Column::poseidon2_hash_num_perm_rounds_rem, Column::poseidon2_hash_output, Column::poseidon2_hash_sel, Column::poseidon2_hash_start, Column::scalar_mul_bit_idx, Column::scalar_mul_point_inf, Column::scalar_mul_point_x, Column::scalar_mul_point_y, Column::scalar_mul_res_inf, Column::scalar_mul_res_x, Column::scalar_mul_res_y, Column::scalar_mul_scalar, Column::scalar_mul_sel, Column::scalar_mul_start, Column::scalar_mul_temp_inf, Column::scalar_mul_temp_x, Column::scalar_mul_temp_y, Column::sha256_a, Column::sha256_b, Column::sha256_c, Column::sha256_d, Column::sha256_e, Column::sha256_f, Column::sha256_g, Column::sha256_h, Column::sha256_helper_w0, Column::sha256_helper_w1, Column::sha256_helper_w10, Column::sha256_helper_w11, Column::sha256_helper_w12, Column::sha256_helper_w13, Column::sha256_helper_w14, Column::sha256_helper_w15, Column::sha256_helper_w2, Column::sha256_helper_w3, Column::sha256_helper_w4, Column::sha256_helper_w5, Column::sha256_helper_w6, Column::sha256_helper_w7, Column::sha256_helper_w8, Column::sha256_helper_w9, Column::sha256_rounds_remaining, Column::sha256_sel, Column::sha256_start, Column::to_radix_acc, Column::to_radix_acc_under_p, Column::to_radix_exponent, Column::to_radix_limb, Column::to_radix_limb_eq_p, Column::to_radix_limb_index, Column::to_radix_limb_lt_p, Column::to_radix_not_padding_limb, Column::to_radix_radix, Column::to_radix_safe_limbs, Column::to_radix_sel, Column::to_radix_start, Column::to_radix_value +#define AVM2_SHIFTED_COLUMNS ColumnAndShifts::bc_decomposition_bytes_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_1_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_10_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_11_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_12_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_13_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_14_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_15_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_16_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_17_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_18_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_19_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_2_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_20_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_21_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_22_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_23_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_24_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_25_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_26_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_27_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_28_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_29_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_3_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_30_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_31_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_32_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_33_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_34_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_35_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_4_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_5_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_6_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_7_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_8_shift, ColumnAndShifts::bc_decomposition_bytes_pc_plus_9_shift, ColumnAndShifts::bc_decomposition_bytes_remaining_shift, ColumnAndShifts::bc_decomposition_id_shift, ColumnAndShifts::bc_decomposition_pc_shift, ColumnAndShifts::bc_decomposition_sel_shift, ColumnAndShifts::bc_hashing_bytecode_id_shift, ColumnAndShifts::bc_hashing_incremental_hash_shift, ColumnAndShifts::bc_hashing_pc_index_shift, ColumnAndShifts::bc_hashing_sel_shift, ColumnAndShifts::bc_hashing_start_shift, ColumnAndShifts::bitwise_acc_ia_shift, ColumnAndShifts::bitwise_acc_ib_shift, ColumnAndShifts::bitwise_acc_ic_shift, ColumnAndShifts::bitwise_ctr_shift, ColumnAndShifts::bitwise_op_id_shift, ColumnAndShifts::execution_sel_shift, ColumnAndShifts::poseidon2_hash_a_0_shift, ColumnAndShifts::poseidon2_hash_a_1_shift, ColumnAndShifts::poseidon2_hash_a_2_shift, ColumnAndShifts::poseidon2_hash_a_3_shift, ColumnAndShifts::poseidon2_hash_input_0_shift, ColumnAndShifts::poseidon2_hash_input_1_shift, ColumnAndShifts::poseidon2_hash_input_2_shift, ColumnAndShifts::poseidon2_hash_num_perm_rounds_rem_shift, ColumnAndShifts::poseidon2_hash_output_shift, ColumnAndShifts::poseidon2_hash_sel_shift, ColumnAndShifts::poseidon2_hash_start_shift, ColumnAndShifts::scalar_mul_bit_idx_shift, ColumnAndShifts::scalar_mul_point_inf_shift, ColumnAndShifts::scalar_mul_point_x_shift, ColumnAndShifts::scalar_mul_point_y_shift, ColumnAndShifts::scalar_mul_res_inf_shift, ColumnAndShifts::scalar_mul_res_x_shift, ColumnAndShifts::scalar_mul_res_y_shift, ColumnAndShifts::scalar_mul_scalar_shift, ColumnAndShifts::scalar_mul_sel_shift, ColumnAndShifts::scalar_mul_start_shift, ColumnAndShifts::scalar_mul_temp_inf_shift, ColumnAndShifts::scalar_mul_temp_x_shift, ColumnAndShifts::scalar_mul_temp_y_shift, ColumnAndShifts::sha256_a_shift, ColumnAndShifts::sha256_b_shift, ColumnAndShifts::sha256_c_shift, ColumnAndShifts::sha256_d_shift, ColumnAndShifts::sha256_e_shift, ColumnAndShifts::sha256_f_shift, ColumnAndShifts::sha256_g_shift, ColumnAndShifts::sha256_h_shift, ColumnAndShifts::sha256_helper_w0_shift, ColumnAndShifts::sha256_helper_w1_shift, ColumnAndShifts::sha256_helper_w10_shift, ColumnAndShifts::sha256_helper_w11_shift, ColumnAndShifts::sha256_helper_w12_shift, ColumnAndShifts::sha256_helper_w13_shift, ColumnAndShifts::sha256_helper_w14_shift, ColumnAndShifts::sha256_helper_w15_shift, ColumnAndShifts::sha256_helper_w2_shift, ColumnAndShifts::sha256_helper_w3_shift, ColumnAndShifts::sha256_helper_w4_shift, ColumnAndShifts::sha256_helper_w5_shift, ColumnAndShifts::sha256_helper_w6_shift, ColumnAndShifts::sha256_helper_w7_shift, ColumnAndShifts::sha256_helper_w8_shift, ColumnAndShifts::sha256_helper_w9_shift, ColumnAndShifts::sha256_rounds_remaining_shift, ColumnAndShifts::sha256_sel_shift, ColumnAndShifts::sha256_start_shift, ColumnAndShifts::to_radix_acc_shift, ColumnAndShifts::to_radix_acc_under_p_shift, ColumnAndShifts::to_radix_exponent_shift, ColumnAndShifts::to_radix_limb_shift, ColumnAndShifts::to_radix_limb_eq_p_shift, ColumnAndShifts::to_radix_limb_index_shift, ColumnAndShifts::to_radix_limb_lt_p_shift, ColumnAndShifts::to_radix_not_padding_limb_shift, ColumnAndShifts::to_radix_radix_shift, ColumnAndShifts::to_radix_safe_limbs_shift, ColumnAndShifts::to_radix_sel_shift, ColumnAndShifts::to_radix_start_shift, ColumnAndShifts::to_radix_value_shift // clang-format on // All columns minus shifts. @@ -31,8 +31,8 @@ enum class ColumnAndShifts { SENTINEL_DO_NOT_USE, }; -constexpr auto NUM_COLUMNS_WITH_SHIFTS = 912; -constexpr auto NUM_COLUMNS_WITHOUT_SHIFTS = 810; +constexpr auto NUM_COLUMNS_WITH_SHIFTS = 965; +constexpr auto NUM_COLUMNS_WITHOUT_SHIFTS = 850; constexpr auto TO_BE_SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM2_TO_BE_SHIFTED_COLUMNS }; }(); constexpr auto SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM2_SHIFTED_COLUMNS }; }(); static_assert(TO_BE_SHIFTED_COLUMNS_ARRAY.size() == SHIFTED_COLUMNS_ARRAY.size()); diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.cpp b/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.cpp index 1c03a5ead942..4c87dc0ef0f5 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.cpp @@ -111,4 +111,4 @@ std::vector AvmFlavor::VerificationKey::to_field return elements; } -} // namespace bb::avm2 \ No newline at end of file +} // namespace bb::avm2 diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp index c3dc8eb1ec9c..6756204df4fd 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp @@ -32,6 +32,7 @@ #include "relations/range_check.hpp" #include "relations/scalar_mul.hpp" #include "relations/sha256.hpp" +#include "relations/to_radix.hpp" // Lookup and permutation relations #include "relations/lookups_bc_decomposition.hpp" @@ -44,6 +45,7 @@ #include "relations/lookups_range_check.hpp" #include "relations/lookups_scalar_mul.hpp" #include "relations/lookups_sha256.hpp" +#include "relations/lookups_to_radix.hpp" // Metaprogramming to concatenate tuple types. template using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); @@ -85,13 +87,13 @@ class AvmFlavor { // This flavor would not be used with ZK Sumcheck static constexpr bool HasZK = false; - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 38; - static constexpr size_t NUM_WITNESS_ENTITIES = 772; - static constexpr size_t NUM_SHIFTED_ENTITIES = 102; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 44; + static constexpr size_t NUM_WITNESS_ENTITIES = 806; + static constexpr size_t NUM_SHIFTED_ENTITIES = 115; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 912; + static constexpr size_t NUM_ALL_ENTITIES = 965; // Need to be templated for recursive verifier template @@ -110,7 +112,8 @@ class AvmFlavor { avm2::poseidon2_perm, avm2::range_check, avm2::scalar_mul, - avm2::sha256>; + avm2::sha256, + avm2::to_radix>; using MainRelations = MainRelations_; @@ -145,7 +148,13 @@ class AvmFlavor { lookup_range_check_r7_is_u16_relation, lookup_scalar_mul_add_relation, lookup_scalar_mul_double_relation, - lookup_sha256_round_constant_relation>; + lookup_scalar_mul_to_radix_relation, + lookup_sha256_round_constant_relation, + lookup_to_radix_fetch_p_limb_relation, + lookup_to_radix_fetch_safe_limbs_relation, + lookup_to_radix_limb_less_than_radix_range_relation, + lookup_to_radix_limb_p_diff_range_relation, + lookup_to_radix_limb_range_relation>; using LookupRelations = LookupRelations_; @@ -403,6 +412,9 @@ class AvmFlavor { this->precomputed_first_row = verification_key->precomputed_first_row; this->precomputed_instr_size_in_bytes = verification_key->precomputed_instr_size_in_bytes; this->precomputed_integral_tag_length = verification_key->precomputed_integral_tag_length; + this->precomputed_p_decomposition_limb = verification_key->precomputed_p_decomposition_limb; + this->precomputed_p_decomposition_limb_index = verification_key->precomputed_p_decomposition_limb_index; + this->precomputed_p_decomposition_radix = verification_key->precomputed_p_decomposition_radix; this->precomputed_power_of_2 = verification_key->precomputed_power_of_2; this->precomputed_sel_bitwise = verification_key->precomputed_sel_bitwise; this->precomputed_sel_integral_tag = verification_key->precomputed_sel_integral_tag; @@ -424,13 +436,16 @@ class AvmFlavor { this->precomputed_sel_op_dc_7 = verification_key->precomputed_sel_op_dc_7; this->precomputed_sel_op_dc_8 = verification_key->precomputed_sel_op_dc_8; this->precomputed_sel_op_dc_9 = verification_key->precomputed_sel_op_dc_9; + this->precomputed_sel_p_decomposition = verification_key->precomputed_sel_p_decomposition; this->precomputed_sel_range_16 = verification_key->precomputed_sel_range_16; this->precomputed_sel_range_8 = verification_key->precomputed_sel_range_8; this->precomputed_sel_range_wire_opcode = verification_key->precomputed_sel_range_wire_opcode; this->precomputed_sel_sha256_compression = verification_key->precomputed_sel_sha256_compression; + this->precomputed_sel_to_radix_safe_limbs = verification_key->precomputed_sel_to_radix_safe_limbs; this->precomputed_sel_unary = verification_key->precomputed_sel_unary; this->precomputed_sha256_compression_round_constant = verification_key->precomputed_sha256_compression_round_constant; + this->precomputed_to_radix_safe_limbs = verification_key->precomputed_to_radix_safe_limbs; this->precomputed_zero = verification_key->precomputed_zero; } }; diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_scalar_mul.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_scalar_mul.hpp index 25efafab9096..6273bdd2af3a 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_scalar_mul.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_scalar_mul.hpp @@ -10,6 +10,104 @@ namespace bb::avm2 { +/////////////////// lookup_scalar_mul_to_radix /////////////////// + +class lookup_scalar_mul_to_radix_settings { + public: + static constexpr std::string_view NAME = "LOOKUP_SCALAR_MUL_TO_RADIX"; + static constexpr std::string_view RELATION_NAME = "scalar_mul"; + + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 4; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + // Columns using the Column enum. + static constexpr Column SRC_SELECTOR = Column::scalar_mul_sel; + static constexpr Column DST_SELECTOR = Column::to_radix_sel; + static constexpr Column COUNTS = Column::lookup_scalar_mul_to_radix_counts; + static constexpr Column INVERSES = Column::lookup_scalar_mul_to_radix_inv; + static constexpr std::array SRC_COLUMNS = { + ColumnAndShifts::scalar_mul_scalar, + ColumnAndShifts::scalar_mul_bit, + ColumnAndShifts::scalar_mul_bit_idx, + ColumnAndShifts::scalar_mul_bit_radix + }; + static constexpr std::array DST_COLUMNS = { + ColumnAndShifts::to_radix_value, + ColumnAndShifts::to_radix_limb, + ColumnAndShifts::to_radix_limb_index, + ColumnAndShifts::to_radix_radix + }; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in._scalar_mul_sel() == 1 || in._to_radix_sel() == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in._scalar_mul_sel()); + const auto is_table_entry = View(in._to_radix_sel()); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_entities(AllEntities&& in) + { + return std::forward_as_tuple(in._lookup_scalar_mul_to_radix_inv(), + in._lookup_scalar_mul_to_radix_counts(), + in._scalar_mul_sel(), + in._to_radix_sel(), + in._scalar_mul_scalar(), + in._scalar_mul_bit(), + in._scalar_mul_bit_idx(), + in._scalar_mul_bit_radix(), + in._to_radix_value(), + in._to_radix_limb(), + in._to_radix_limb_index(), + in._to_radix_radix()); + } +}; + +template +class lookup_scalar_mul_to_radix_relation : public GenericLookupRelation { + public: + using Settings = lookup_scalar_mul_to_radix_settings; + static constexpr std::string_view NAME = lookup_scalar_mul_to_radix_settings::NAME; + static constexpr std::string_view RELATION_NAME = lookup_scalar_mul_to_radix_settings::RELATION_NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.lookup_scalar_mul_to_radix_inv.is_zero(); + } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } +}; + /////////////////// lookup_scalar_mul_double /////////////////// class lookup_scalar_mul_double_settings { diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_to_radix.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_to_radix.hpp new file mode 100644 index 000000000000..0b5de70cb909 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_to_radix.hpp @@ -0,0 +1,447 @@ +// AUTOGENERATED FILE +#pragma once + +#include "../columns.hpp" +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include +#include + +namespace bb::avm2 { + +/////////////////// lookup_to_radix_limb_range /////////////////// + +class lookup_to_radix_limb_range_settings { + public: + static constexpr std::string_view NAME = "LOOKUP_TO_RADIX_LIMB_RANGE"; + static constexpr std::string_view RELATION_NAME = "to_radix"; + + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 1; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + // Columns using the Column enum. + static constexpr Column SRC_SELECTOR = Column::to_radix_sel; + static constexpr Column DST_SELECTOR = Column::precomputed_sel_range_8; + static constexpr Column COUNTS = Column::lookup_to_radix_limb_range_counts; + static constexpr Column INVERSES = Column::lookup_to_radix_limb_range_inv; + static constexpr std::array SRC_COLUMNS = { ColumnAndShifts::to_radix_limb }; + static constexpr std::array DST_COLUMNS = { ColumnAndShifts::precomputed_clk }; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in._to_radix_sel() == 1 || in._precomputed_sel_range_8() == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in._to_radix_sel()); + const auto is_table_entry = View(in._precomputed_sel_range_8()); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_entities(AllEntities&& in) + { + return std::forward_as_tuple(in._lookup_to_radix_limb_range_inv(), + in._lookup_to_radix_limb_range_counts(), + in._to_radix_sel(), + in._precomputed_sel_range_8(), + in._to_radix_limb(), + in._precomputed_clk()); + } +}; + +template +class lookup_to_radix_limb_range_relation : public GenericLookupRelation { + public: + using Settings = lookup_to_radix_limb_range_settings; + static constexpr std::string_view NAME = lookup_to_radix_limb_range_settings::NAME; + static constexpr std::string_view RELATION_NAME = lookup_to_radix_limb_range_settings::RELATION_NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.lookup_to_radix_limb_range_inv.is_zero(); + } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } +}; + +/////////////////// lookup_to_radix_limb_less_than_radix_range /////////////////// + +class lookup_to_radix_limb_less_than_radix_range_settings { + public: + static constexpr std::string_view NAME = "LOOKUP_TO_RADIX_LIMB_LESS_THAN_RADIX_RANGE"; + static constexpr std::string_view RELATION_NAME = "to_radix"; + + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 1; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + // Columns using the Column enum. + static constexpr Column SRC_SELECTOR = Column::to_radix_sel; + static constexpr Column DST_SELECTOR = Column::precomputed_sel_range_8; + static constexpr Column COUNTS = Column::lookup_to_radix_limb_less_than_radix_range_counts; + static constexpr Column INVERSES = Column::lookup_to_radix_limb_less_than_radix_range_inv; + static constexpr std::array SRC_COLUMNS = { + ColumnAndShifts::to_radix_limb_radix_diff + }; + static constexpr std::array DST_COLUMNS = { ColumnAndShifts::precomputed_clk }; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in._to_radix_sel() == 1 || in._precomputed_sel_range_8() == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in._to_radix_sel()); + const auto is_table_entry = View(in._precomputed_sel_range_8()); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_entities(AllEntities&& in) + { + return std::forward_as_tuple(in._lookup_to_radix_limb_less_than_radix_range_inv(), + in._lookup_to_radix_limb_less_than_radix_range_counts(), + in._to_radix_sel(), + in._precomputed_sel_range_8(), + in._to_radix_limb_radix_diff(), + in._precomputed_clk()); + } +}; + +template +class lookup_to_radix_limb_less_than_radix_range_relation + : public GenericLookupRelation { + public: + using Settings = lookup_to_radix_limb_less_than_radix_range_settings; + static constexpr std::string_view NAME = lookup_to_radix_limb_less_than_radix_range_settings::NAME; + static constexpr std::string_view RELATION_NAME = + lookup_to_radix_limb_less_than_radix_range_settings::RELATION_NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.lookup_to_radix_limb_less_than_radix_range_inv.is_zero(); + } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } +}; + +/////////////////// lookup_to_radix_fetch_safe_limbs /////////////////// + +class lookup_to_radix_fetch_safe_limbs_settings { + public: + static constexpr std::string_view NAME = "LOOKUP_TO_RADIX_FETCH_SAFE_LIMBS"; + static constexpr std::string_view RELATION_NAME = "to_radix"; + + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 2; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + // Columns using the Column enum. + static constexpr Column SRC_SELECTOR = Column::to_radix_start; + static constexpr Column DST_SELECTOR = Column::precomputed_sel_to_radix_safe_limbs; + static constexpr Column COUNTS = Column::lookup_to_radix_fetch_safe_limbs_counts; + static constexpr Column INVERSES = Column::lookup_to_radix_fetch_safe_limbs_inv; + static constexpr std::array SRC_COLUMNS = { + ColumnAndShifts::to_radix_radix, ColumnAndShifts::to_radix_safe_limbs + }; + static constexpr std::array DST_COLUMNS = { + ColumnAndShifts::precomputed_clk, ColumnAndShifts::precomputed_to_radix_safe_limbs + }; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in._to_radix_start() == 1 || in._precomputed_sel_to_radix_safe_limbs() == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in._to_radix_start()); + const auto is_table_entry = View(in._precomputed_sel_to_radix_safe_limbs()); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_entities(AllEntities&& in) + { + return std::forward_as_tuple(in._lookup_to_radix_fetch_safe_limbs_inv(), + in._lookup_to_radix_fetch_safe_limbs_counts(), + in._to_radix_start(), + in._precomputed_sel_to_radix_safe_limbs(), + in._to_radix_radix(), + in._to_radix_safe_limbs(), + in._precomputed_clk(), + in._precomputed_to_radix_safe_limbs()); + } +}; + +template +class lookup_to_radix_fetch_safe_limbs_relation + : public GenericLookupRelation { + public: + using Settings = lookup_to_radix_fetch_safe_limbs_settings; + static constexpr std::string_view NAME = lookup_to_radix_fetch_safe_limbs_settings::NAME; + static constexpr std::string_view RELATION_NAME = lookup_to_radix_fetch_safe_limbs_settings::RELATION_NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.lookup_to_radix_fetch_safe_limbs_inv.is_zero(); + } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } +}; + +/////////////////// lookup_to_radix_fetch_p_limb /////////////////// + +class lookup_to_radix_fetch_p_limb_settings { + public: + static constexpr std::string_view NAME = "LOOKUP_TO_RADIX_FETCH_P_LIMB"; + static constexpr std::string_view RELATION_NAME = "to_radix"; + + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 3; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + // Columns using the Column enum. + static constexpr Column SRC_SELECTOR = Column::to_radix_not_padding_limb; + static constexpr Column DST_SELECTOR = Column::precomputed_sel_p_decomposition; + static constexpr Column COUNTS = Column::lookup_to_radix_fetch_p_limb_counts; + static constexpr Column INVERSES = Column::lookup_to_radix_fetch_p_limb_inv; + static constexpr std::array SRC_COLUMNS = { + ColumnAndShifts::to_radix_radix, ColumnAndShifts::to_radix_limb_index, ColumnAndShifts::to_radix_p_limb + }; + static constexpr std::array DST_COLUMNS = { + ColumnAndShifts::precomputed_p_decomposition_radix, + ColumnAndShifts::precomputed_p_decomposition_limb_index, + ColumnAndShifts::precomputed_p_decomposition_limb + }; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in._to_radix_not_padding_limb() == 1 || in._precomputed_sel_p_decomposition() == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in._to_radix_not_padding_limb()); + const auto is_table_entry = View(in._precomputed_sel_p_decomposition()); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_entities(AllEntities&& in) + { + return std::forward_as_tuple(in._lookup_to_radix_fetch_p_limb_inv(), + in._lookup_to_radix_fetch_p_limb_counts(), + in._to_radix_not_padding_limb(), + in._precomputed_sel_p_decomposition(), + in._to_radix_radix(), + in._to_radix_limb_index(), + in._to_radix_p_limb(), + in._precomputed_p_decomposition_radix(), + in._precomputed_p_decomposition_limb_index(), + in._precomputed_p_decomposition_limb()); + } +}; + +template +class lookup_to_radix_fetch_p_limb_relation : public GenericLookupRelation { + public: + using Settings = lookup_to_radix_fetch_p_limb_settings; + static constexpr std::string_view NAME = lookup_to_radix_fetch_p_limb_settings::NAME; + static constexpr std::string_view RELATION_NAME = lookup_to_radix_fetch_p_limb_settings::RELATION_NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.lookup_to_radix_fetch_p_limb_inv.is_zero(); + } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } +}; + +/////////////////// lookup_to_radix_limb_p_diff_range /////////////////// + +class lookup_to_radix_limb_p_diff_range_settings { + public: + static constexpr std::string_view NAME = "LOOKUP_TO_RADIX_LIMB_P_DIFF_RANGE"; + static constexpr std::string_view RELATION_NAME = "to_radix"; + + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 1; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + // Columns using the Column enum. + static constexpr Column SRC_SELECTOR = Column::to_radix_not_padding_limb; + static constexpr Column DST_SELECTOR = Column::precomputed_sel_range_8; + static constexpr Column COUNTS = Column::lookup_to_radix_limb_p_diff_range_counts; + static constexpr Column INVERSES = Column::lookup_to_radix_limb_p_diff_range_inv; + static constexpr std::array SRC_COLUMNS = { + ColumnAndShifts::to_radix_limb_p_diff + }; + static constexpr std::array DST_COLUMNS = { ColumnAndShifts::precomputed_clk }; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in._to_radix_not_padding_limb() == 1 || in._precomputed_sel_range_8() == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in._to_radix_not_padding_limb()); + const auto is_table_entry = View(in._precomputed_sel_range_8()); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_entities(AllEntities&& in) + { + return std::forward_as_tuple(in._lookup_to_radix_limb_p_diff_range_inv(), + in._lookup_to_radix_limb_p_diff_range_counts(), + in._to_radix_not_padding_limb(), + in._precomputed_sel_range_8(), + in._to_radix_limb_p_diff(), + in._precomputed_clk()); + } +}; + +template +class lookup_to_radix_limb_p_diff_range_relation + : public GenericLookupRelation { + public: + using Settings = lookup_to_radix_limb_p_diff_range_settings; + static constexpr std::string_view NAME = lookup_to_radix_limb_p_diff_range_settings::NAME; + static constexpr std::string_view RELATION_NAME = lookup_to_radix_limb_p_diff_range_settings::RELATION_NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.lookup_to_radix_limb_p_diff_range_inv.is_zero(); + } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } +}; + +} // namespace bb::avm2 diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/to_radix.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/to_radix.hpp new file mode 100644 index 000000000000..d647f9f95c2d --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/to_radix.hpp @@ -0,0 +1,339 @@ +// AUTOGENERATED FILE +#pragma once + +#include + +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/relations/relation_types.hpp" + +namespace bb::avm2 { + +template class to_radixImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 4, + 3, 3, 3, 3, 3, 3, 4, 5, 4, 3, 3, 3, 3, 5, + 3, 3, 3, 3, 3, 5, 3, 4, 3, 3, 3, 3 }; + + template inline static bool skip(const AllEntities& in) + { + const auto& new_term = in; + return (new_term.to_radix_sel).is_zero(); + } + + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& new_term, + [[maybe_unused]] const RelationParameters&, + [[maybe_unused]] const FF& scaling_factor) + { + const auto to_radix_LATCH_CONDITION = new_term.to_radix_end + new_term.precomputed_first_row; + const auto to_radix_REM = (new_term.to_radix_value - new_term.to_radix_acc); + const auto to_radix_safety_diff = (new_term.to_radix_limb_index - new_term.to_radix_safe_limbs); + const auto to_radix_LIMB_LT_P = ((new_term.to_radix_p_limb - new_term.to_radix_limb) - FF(1)); + const auto to_radix_LIMB_GT_P = ((new_term.to_radix_limb - new_term.to_radix_p_limb) - FF(1)); + const auto to_radix_LIMB_EQ_P = (new_term.to_radix_limb - new_term.to_radix_p_limb) * FF(256); + + { + using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_sel * (FF(1) - new_term.to_radix_sel); + tmp *= scaling_factor; + std::get<0>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<1, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_start * (FF(1) - new_term.to_radix_start); + tmp *= scaling_factor; + std::get<1>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<2, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_end * (FF(1) - new_term.to_radix_end); + tmp *= scaling_factor; + std::get<2>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<3, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_end * new_term.precomputed_first_row; + tmp *= scaling_factor; + std::get<3>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<4, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_sel_shift * (new_term.to_radix_start_shift - to_radix_LATCH_CONDITION); + tmp *= scaling_factor; + std::get<4>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<5, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_start * (FF(1) - new_term.to_radix_sel); + tmp *= scaling_factor; + std::get<5>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<6, ContainerOverSubrelations>; + auto tmp = (new_term.to_radix_sel_shift - new_term.to_radix_sel) * (FF(1) - to_radix_LATCH_CONDITION); + tmp *= scaling_factor; + std::get<6>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<7, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_end * (FF(1) - new_term.to_radix_sel); + tmp *= scaling_factor; + std::get<7>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<8, ContainerOverSubrelations>; + auto tmp = (new_term.to_radix_sel * (FF(1) - new_term.to_radix_end) - new_term.to_radix_not_end); + tmp *= scaling_factor; + std::get<8>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<9, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_padding_limb * (FF(1) - new_term.to_radix_not_padding_limb); + tmp *= scaling_factor; + std::get<9>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<10, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_start * (new_term.to_radix_exponent - FF(1)); + tmp *= scaling_factor; + std::get<10>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<11, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * new_term.to_radix_not_padding_limb_shift * + (new_term.to_radix_exponent * new_term.to_radix_radix - new_term.to_radix_exponent_shift); + tmp *= scaling_factor; + std::get<11>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<12, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_start * (FF(1) - new_term.to_radix_not_padding_limb); + tmp *= scaling_factor; + std::get<12>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<13, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * + (((FF(0) - new_term.to_radix_not_padding_limb) * new_term.to_radix_is_unsafe_limb + + new_term.to_radix_not_padding_limb) - + new_term.to_radix_not_padding_limb_shift); + tmp *= scaling_factor; + std::get<13>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<14, ContainerOverSubrelations>; + auto tmp = (FF(1) - new_term.to_radix_not_padding_limb) * new_term.to_radix_exponent; + tmp *= scaling_factor; + std::get<14>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<15, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_found * (FF(1) - new_term.to_radix_found); + tmp *= scaling_factor; + std::get<15>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<16, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_start * new_term.to_radix_limb_index; + tmp *= scaling_factor; + std::get<16>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<17, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * + ((new_term.to_radix_limb_index + FF(1)) - new_term.to_radix_limb_index_shift); + tmp *= scaling_factor; + std::get<17>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<18, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_sel * (((new_term.to_radix_radix - FF(1)) - new_term.to_radix_limb) - + new_term.to_radix_limb_radix_diff); + tmp *= scaling_factor; + std::get<18>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<19, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_start * (new_term.to_radix_acc - new_term.to_radix_limb); + tmp *= scaling_factor; + std::get<19>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<20, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * + ((new_term.to_radix_acc + new_term.to_radix_exponent_shift * new_term.to_radix_limb_shift) - + new_term.to_radix_acc_shift); + tmp *= scaling_factor; + std::get<20>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<21, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_sel * + ((to_radix_REM * (new_term.to_radix_found * (FF(1) - new_term.to_radix_rem_inverse) + + new_term.to_radix_rem_inverse) - + FF(1)) + + new_term.to_radix_found); + tmp *= scaling_factor; + std::get<21>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<22, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * new_term.to_radix_found * new_term.to_radix_limb_shift; + tmp *= scaling_factor; + std::get<22>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<23, ContainerOverSubrelations>; + auto tmp = (FF(1) - new_term.to_radix_found) * new_term.to_radix_end; + tmp *= scaling_factor; + std::get<23>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<24, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_is_unsafe_limb * (FF(1) - new_term.to_radix_is_unsafe_limb); + tmp *= scaling_factor; + std::get<24>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<25, ContainerOverSubrelations>; + auto tmp = (FF(1) - new_term.to_radix_not_padding_limb) * new_term.to_radix_limb; + tmp *= scaling_factor; + std::get<25>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<26, ContainerOverSubrelations>; + auto tmp = (FF(1) - new_term.to_radix_not_padding_limb) * new_term.to_radix_p_limb; + tmp *= scaling_factor; + std::get<26>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<27, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_sel * + ((to_radix_safety_diff * + (new_term.to_radix_is_unsafe_limb * (FF(1) - new_term.to_radix_safety_diff_inverse) + + new_term.to_radix_safety_diff_inverse) - + FF(1)) + + new_term.to_radix_is_unsafe_limb); + tmp *= scaling_factor; + std::get<27>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<28, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_acc_under_p * (FF(1) - new_term.to_radix_acc_under_p); + tmp *= scaling_factor; + std::get<28>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<29, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_limb_lt_p * (FF(1) - new_term.to_radix_limb_lt_p); + tmp *= scaling_factor; + std::get<29>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<30, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_limb_eq_p * (FF(1) - new_term.to_radix_limb_eq_p); + tmp *= scaling_factor; + std::get<30>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<31, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_limb_eq_p * new_term.to_radix_limb_lt_p; + tmp *= scaling_factor; + std::get<31>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<32, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_limb_lt_p * (to_radix_LIMB_LT_P - new_term.to_radix_limb_p_diff); + tmp *= scaling_factor; + std::get<32>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<33, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_sel * (FF(1) - new_term.to_radix_limb_lt_p) * + (((to_radix_LIMB_EQ_P - to_radix_LIMB_GT_P) * new_term.to_radix_limb_eq_p + to_radix_LIMB_GT_P) - + new_term.to_radix_limb_p_diff); + tmp *= scaling_factor; + std::get<33>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<34, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_start * (new_term.to_radix_acc_under_p - new_term.to_radix_limb_lt_p); + tmp *= scaling_factor; + std::get<34>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<35, ContainerOverSubrelations>; + auto tmp = + new_term.to_radix_not_end * (((new_term.to_radix_acc_under_p - new_term.to_radix_limb_lt_p_shift) * + new_term.to_radix_limb_eq_p_shift + + new_term.to_radix_limb_lt_p_shift) - + new_term.to_radix_acc_under_p_shift); + tmp *= scaling_factor; + std::get<35>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<36, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_is_unsafe_limb * (FF(1) - new_term.to_radix_acc_under_p); + tmp *= scaling_factor; + std::get<36>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<37, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * (new_term.to_radix_radix - new_term.to_radix_radix_shift); + tmp *= scaling_factor; + std::get<37>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<38, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * (new_term.to_radix_value - new_term.to_radix_value_shift); + tmp *= scaling_factor; + std::get<38>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<39, ContainerOverSubrelations>; + auto tmp = new_term.to_radix_not_end * (new_term.to_radix_safe_limbs - new_term.to_radix_safe_limbs_shift); + tmp *= scaling_factor; + std::get<39>(evals) += typename Accumulator::View(tmp); + } + } +}; + +template class to_radix : public Relation> { + public: + static constexpr const std::string_view NAME = "to_radix"; + + static std::string get_subrelation_label(size_t index) + { + switch (index) { + case 4: + return "START_AFTER_LATCH"; + case 5: + return "SELECTOR_ON_START"; + case 6: + return "SELECTOR_CONSISTENCY"; + case 36: + return "OVERFLOW_CHECK"; + case 37: + return "CONSTANT_CONSISTENCY_RADIX"; + case 38: + return "CONSTANT_CONSISTENCY_VALUE"; + case 39: + return "CONSTANT_CONSISTENCY_SAFE_LIMBS"; + } + return std::to_string(index); + } + + // Subrelation indices constants, to be used in tests. + static constexpr size_t SR_START_AFTER_LATCH = 4; + static constexpr size_t SR_SELECTOR_ON_START = 5; + static constexpr size_t SR_SELECTOR_CONSISTENCY = 6; + static constexpr size_t SR_OVERFLOW_CHECK = 36; + static constexpr size_t SR_CONSTANT_CONSISTENCY_RADIX = 37; + static constexpr size_t SR_CONSTANT_CONSISTENCY_VALUE = 38; + static constexpr size_t SR_CONSTANT_CONSISTENCY_SAFE_LIMBS = 39; +}; + +} // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.cpp index 601f8c6a57eb..ab5196ccf698 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.cpp @@ -18,19 +18,18 @@ EmbeddedCurvePoint Ecc::add(const EmbeddedCurvePoint& p, const EmbeddedCurvePoin EmbeddedCurvePoint Ecc::scalar_mul(const EmbeddedCurvePoint& point, const FF& scalar) { - uint256_t scalar_integer = static_cast(scalar); auto intermediate_states = std::vector(254); + auto bits = to_radix.to_le_bits(scalar, 254); // First iteration does conditional assignment instead of addition EmbeddedCurvePoint temp = point; - // TODO(Alvaro): Call to radix here when it is implemented. - bool bit = scalar_integer.get_bit(0); + bool bit = bits[0]; EmbeddedCurvePoint result = bit ? temp : EmbeddedCurvePoint::infinity(); intermediate_states[0] = { result, temp, bit }; for (size_t i = 1; i < 254; i++) { - bit = scalar_integer.get_bit(i); + bit = bits[i]; temp = add(temp, temp); if (bit) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.hpp index a084f150f867..b0c41fa446a4 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.hpp @@ -1,8 +1,10 @@ #pragma once +#include "barretenberg/vm2/common/aztec_types.hpp" #include "barretenberg/vm2/common/field.hpp" #include "barretenberg/vm2/simulation/events/ecc_events.hpp" #include "barretenberg/vm2/simulation/events/event_emitter.hpp" +#include "barretenberg/vm2/simulation/to_radix.hpp" namespace bb::avm2::simulation { @@ -10,22 +12,26 @@ class EccInterface { public: virtual ~EccInterface() = default; virtual EmbeddedCurvePoint add(const EmbeddedCurvePoint& p, const EmbeddedCurvePoint& q) = 0; + virtual EmbeddedCurvePoint scalar_mul(const EmbeddedCurvePoint& point, const FF& scalar) = 0; }; class Ecc : public EccInterface { public: - Ecc(EventEmitterInterface& ecadd_event_emitter, + Ecc(ToRadixInterface& to_radix, + EventEmitterInterface& ecadd_event_emitter, EventEmitterInterface& scalar_mul_event_emitter) : add_events(ecadd_event_emitter) , scalar_mul_events(scalar_mul_event_emitter) + , to_radix(to_radix) {} EmbeddedCurvePoint add(const EmbeddedCurvePoint& p, const EmbeddedCurvePoint& q) override; - EmbeddedCurvePoint scalar_mul(const EmbeddedCurvePoint& point, const FF& scalar); + EmbeddedCurvePoint scalar_mul(const EmbeddedCurvePoint& point, const FF& scalar) override; private: EventEmitterInterface& add_events; EventEmitterInterface& scalar_mul_events; + ToRadixInterface& to_radix; }; } // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.test.cpp index 9164a1e7a76c..d27d172021e2 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/ecc.test.cpp @@ -1,17 +1,18 @@ #include "barretenberg/vm2/simulation/ecc.hpp" -#include +#include "gmock/gmock.h" #include #include "barretenberg/vm2/common/field.hpp" #include "barretenberg/vm2/simulation/events/ecc_events.hpp" #include "barretenberg/vm2/simulation/events/event_emitter.hpp" +#include "barretenberg/vm2/simulation/testing/mock_to_radix.hpp" using ::testing::AllOf; using ::testing::ElementsAre; -using ::testing::ElementsAreArray; -using ::testing::Field; +using ::testing::Return; using ::testing::SizeIs; +using ::testing::StrictMock; namespace bb::avm2::simulation { namespace { @@ -20,8 +21,9 @@ TEST(AvmSimulationEccTest, Add) { EventEmitter ecc_event_emitter; EventEmitter scalar_mul_event_emitter; + StrictMock to_radix; - Ecc ecc(ecc_event_emitter, scalar_mul_event_emitter); + Ecc ecc(to_radix, ecc_event_emitter, scalar_mul_event_emitter); FF p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a"); FF p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60"); @@ -51,10 +53,18 @@ TEST(AvmSimulationEccTest, ScalarMul) { EventEmitter ecc_event_emitter; EventEmitter scalar_mul_event_emitter; + StrictMock to_radix; - Ecc ecc(ecc_event_emitter, scalar_mul_event_emitter); + Ecc ecc(to_radix, ecc_event_emitter, scalar_mul_event_emitter); FF scalar("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7"); + uint256_t scalar_num = scalar; + std::vector bits(254, false); + for (size_t i = 0; i < 254; ++i) { + bits[i] = scalar_num.get_bit(i); + } + + EXPECT_CALL(to_radix, to_le_bits(scalar, 254)).WillOnce(Return(bits)); FF p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a"); FF p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60"); diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp index 7b9cfa41b9da..5053e16186fd 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp @@ -13,6 +13,7 @@ #include "barretenberg/vm2/simulation/events/poseidon2_event.hpp" #include "barretenberg/vm2/simulation/events/sha256_event.hpp" #include "barretenberg/vm2/simulation/events/siloing_event.hpp" +#include "barretenberg/vm2/simulation/events/to_radix_event.hpp" namespace bb::avm2::simulation { @@ -34,6 +35,7 @@ struct EventsContainer { EventEmitterInterface::Container scalar_mul; EventEmitterInterface::Container poseidon2_hash; EventEmitterInterface::Container poseidon2_permutation; + EventEmitterInterface::Container to_radix; }; } // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/to_radix_event.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/to_radix_event.hpp new file mode 100644 index 000000000000..e0c9ba6edd69 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/to_radix_event.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "barretenberg/vm2/common/field.hpp" + +namespace bb::avm2::simulation { + +struct ToRadixEvent { + FF value; + uint32_t radix; + std::vector limbs; + + bool operator==(const ToRadixEvent& other) const = default; +}; + +} // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_to_radix.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_to_radix.hpp new file mode 100644 index 000000000000..d77b3e9d2ddf --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_to_radix.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "barretenberg/vm2/simulation/to_radix.hpp" + +namespace bb::avm2::simulation { + +class MockToRadix : public ToRadixInterface { + public: + MockToRadix(); + ~MockToRadix() override; + + MOCK_METHOD((std::vector), to_le_radix, (const FF& value, uint32_t num_limbs, uint32_t radix), (override)); + MOCK_METHOD((std::vector), to_le_bits, (const FF& value, uint32_t num_limbs), (override)); +}; + +} // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_to_radix.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_to_radix.test.cpp new file mode 100644 index 000000000000..003732a17f7f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_to_radix.test.cpp @@ -0,0 +1,9 @@ +// This is not a test file but we need to use .test.cpp so that it is not included in non-test builds. +#include "barretenberg/vm2/simulation/testing/mock_to_radix.hpp" + +namespace bb::avm2::simulation { + +MockToRadix::MockToRadix() = default; +MockToRadix::~MockToRadix() = default; + +} // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.cpp new file mode 100644 index 000000000000..048caf4d61a1 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.cpp @@ -0,0 +1,51 @@ +#include "barretenberg/vm2/simulation/to_radix.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/vm2/common/to_radix.hpp" +#include "barretenberg/vm2/simulation/events/to_radix_event.hpp" +#include + +namespace bb::avm2::simulation { + +std::vector ToRadix::to_le_radix(const FF& value, uint32_t num_limbs, uint32_t radix) +{ + uint256_t value_integer = static_cast(value); + auto limbs = std::vector(); + size_t radix_index = static_cast(radix); + limbs.reserve(std::max(num_limbs, static_cast(get_p_limbs_per_radix()[radix_index].size()))); + + while (value_integer > 0) { + limbs.push_back(static_cast(value_integer % radix)); + value_integer /= radix; + } + + if (num_limbs > limbs.size()) { + limbs.insert(limbs.end(), num_limbs - limbs.size(), 0); + } + + // The event should never have less limbs than the necessary to perform the decomposition + events.emit(ToRadixEvent{ + .value = value, + .radix = radix, + .limbs = limbs, + }); + + if (num_limbs < limbs.size()) { + limbs.erase(limbs.begin() + num_limbs, limbs.end()); + } + + return limbs; +} + +std::vector ToRadix::to_le_bits(const FF& value, uint32_t num_limbs) +{ + std::vector limbs = to_le_radix(value, num_limbs, 2); + std::vector bits(limbs.size()); + + std::transform(limbs.begin(), limbs.end(), bits.begin(), [](uint8_t val) { + return val != 0; // Convert nonzero values to `true`, zero to `false` + }); + + return bits; +} + +} // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.hpp new file mode 100644 index 000000000000..a7e07e77f4b4 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "barretenberg/vm2/common/field.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" +#include "barretenberg/vm2/simulation/events/to_radix_event.hpp" + +namespace bb::avm2::simulation { + +class ToRadixInterface { + public: + virtual ~ToRadixInterface() = default; + virtual std::vector to_le_radix(const FF& value, uint32_t num_limbs, uint32_t radix) = 0; + virtual std::vector to_le_bits(const FF& value, uint32_t num_limbs) = 0; +}; + +class ToRadix : public ToRadixInterface { + public: + ToRadix(EventEmitterInterface& event_emitter) + : events(event_emitter) + {} + + std::vector to_le_radix(const FF& value, uint32_t num_limbs, uint32_t radix) override; + std::vector to_le_bits(const FF& value, uint32_t num_limbs) override; + + private: + EventEmitterInterface& events; +}; + +} // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.test.cpp new file mode 100644 index 000000000000..8df93219fc7f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/to_radix.test.cpp @@ -0,0 +1,142 @@ +#include "barretenberg/vm2/simulation/to_radix.hpp" + +#include "gmock/gmock.h" +#include +#include + +#include "barretenberg/vm2/common/aztec_types.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" +#include "barretenberg/vm2/simulation/events/to_radix_event.hpp" + +using ::testing::AllOf; +using ::testing::ElementsAre; +using ::testing::Field; +using ::testing::Return; +using ::testing::SizeIs; + +namespace bb::avm2::simulation { +namespace { + +TEST(AvmSimulationToRadixTest, BasicBits) +{ + EventEmitter to_radix_event_emitter; + + ToRadix to_radix(to_radix_event_emitter); + + auto bits = to_radix.to_le_bits(FF::one(), 254); + + std::vector expected_result(254, false); + expected_result[0] = true; + + EXPECT_EQ(bits, expected_result); + + EXPECT_THAT(to_radix_event_emitter.dump_events(), + AllOf(SizeIs(1), + ElementsAre(AllOf(Field(&ToRadixEvent::value, FF::one()), + Field(&ToRadixEvent::radix, 2), + Field(&ToRadixEvent::limbs, SizeIs(254)))))); +} + +TEST(AvmSimulationToRadixTest, ShortBits) +{ + EventEmitter to_radix_event_emitter; + + ToRadix to_radix(to_radix_event_emitter); + + auto bits = to_radix.to_le_bits(FF::one(), 1); + + std::vector expected_result = { true }; + + EXPECT_EQ(bits, expected_result); + + EXPECT_THAT(to_radix_event_emitter.dump_events(), + AllOf(SizeIs(1), ElementsAre(AllOf(Field(&ToRadixEvent::limbs, SizeIs(1)))))); +} + +TEST(AvmSimulationToRadixTest, DecomposeOneBitLargeValue) +{ + EventEmitter to_radix_event_emitter; + + ToRadix to_radix(to_radix_event_emitter); + + auto bits = to_radix.to_le_bits(FF::neg_one(), 1); + + // first bit of p - 1 is zero + std::vector expected_result = { false }; + + EXPECT_EQ(bits, expected_result); + + // 254 limbs are needed to represent p - 1 + EXPECT_THAT(to_radix_event_emitter.dump_events(), + AllOf(SizeIs(1), ElementsAre(AllOf(Field(&ToRadixEvent::limbs, SizeIs(254)))))); +} + +TEST(AvmSimulationToRadixTest, BasicRadix) +{ + EventEmitter to_radix_event_emitter; + + ToRadix to_radix(to_radix_event_emitter); + + auto limbs = to_radix.to_le_radix(FF::one(), 32, 256); + + std::vector expected_result(32, 0); + expected_result[0] = 1; + + EXPECT_EQ(limbs, expected_result); + + EXPECT_THAT(to_radix_event_emitter.dump_events(), + AllOf(SizeIs(1), + ElementsAre(AllOf(Field(&ToRadixEvent::value, FF::one()), + Field(&ToRadixEvent::radix, 256), + Field(&ToRadixEvent::limbs, SizeIs(32)))))); +} + +TEST(AvmSimulationToRadixTest, ShortRadix) +{ + EventEmitter to_radix_event_emitter; + + ToRadix to_radix(to_radix_event_emitter); + + auto limbs = to_radix.to_le_radix(FF::one(), 1, 256); + + std::vector expected_result = { 1 }; + + EXPECT_EQ(limbs, expected_result); + + EXPECT_THAT(to_radix_event_emitter.dump_events(), + AllOf(SizeIs(1), ElementsAre(Field(&ToRadixEvent::limbs, SizeIs(1))))); +} + +TEST(AvmSimulationToRadixTest, DecomposeOneRadixLargerValue) +{ + EventEmitter to_radix_event_emitter; + + ToRadix to_radix(to_radix_event_emitter); + + auto limbs = to_radix.to_le_radix(FF::neg_one(), 1, 256); + + // first byte of p - 1 is zero + std::vector expected_result = { 0 }; + + EXPECT_EQ(limbs, expected_result); + + // 32 limbs are needed to represent p - 1 + EXPECT_THAT(to_radix_event_emitter.dump_events(), + AllOf(SizeIs(1), ElementsAre(AllOf(Field(&ToRadixEvent::limbs, SizeIs(32)))))); +} + +TEST(AvmSimulationToRadixTest, DecomposeInDecimal) +{ + EventEmitter to_radix_event_emitter; + + ToRadix to_radix(to_radix_event_emitter); + + auto limbs = to_radix.to_le_radix(1337, 4, 10); + + std::vector expected_result = { 7, 3, 3, 1 }; + + EXPECT_EQ(limbs, expected_result); +} + +} // namespace +} // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp index 824c46ff056f..a0c9b45ab0c1 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp @@ -23,12 +23,14 @@ #include "barretenberg/vm2/simulation/events/memory_event.hpp" #include "barretenberg/vm2/simulation/events/sha256_event.hpp" #include "barretenberg/vm2/simulation/events/siloing_event.hpp" +#include "barretenberg/vm2/simulation/events/to_radix_event.hpp" #include "barretenberg/vm2/simulation/execution.hpp" #include "barretenberg/vm2/simulation/lib/instruction_info.hpp" #include "barretenberg/vm2/simulation/lib/raw_data_dbs.hpp" #include "barretenberg/vm2/simulation/poseidon2.hpp" #include "barretenberg/vm2/simulation/sha256.hpp" #include "barretenberg/vm2/simulation/siloing.hpp" +#include "barretenberg/vm2/simulation/to_radix.hpp" #include "barretenberg/vm2/simulation/tx_execution.hpp" namespace bb::avm2 { @@ -70,6 +72,7 @@ template EventsContainer AvmSimulationHelper::simulate_with_setting typename S::template DefaultEventEmitter scalar_mul_emitter; typename S::template DefaultEventEmitter poseidon2_hash_emitter; typename S::template DefaultEventEmitter poseidon2_perm_emitter; + typename S::template DefaultEventEmitter to_radix_emitter; Poseidon2 poseidon2(poseidon2_hash_emitter, poseidon2_perm_emitter); @@ -98,7 +101,8 @@ template EventsContainer AvmSimulationHelper::simulate_with_setting Execution execution(alu, addressing, context_provider, context_stack, instruction_info_db, execution_emitter); TxExecution tx_execution(execution); Sha256 sha256(sha256_compression_emitter); - Ecc ecc_add(ecc_add_emitter, scalar_mul_emitter); + ToRadix to_radix(to_radix_emitter); + Ecc ecc_add(to_radix, ecc_add_emitter, scalar_mul_emitter); tx_execution.simulate({ .enqueued_calls = inputs.hints.enqueuedCalls }); @@ -118,7 +122,8 @@ template EventsContainer AvmSimulationHelper::simulate_with_setting ecc_add_emitter.dump_events(), scalar_mul_emitter.dump_events(), poseidon2_hash_emitter.dump_events(), - poseidon2_perm_emitter.dump_events() }; + poseidon2_perm_emitter.dump_events(), + to_radix_emitter.dump_events() }; } EventsContainer AvmSimulationHelper::simulate() diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/lookup_into_p_decomposition.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/lookup_into_p_decomposition.hpp new file mode 100644 index 000000000000..99e5d5c90ae7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/lookup_into_p_decomposition.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include "barretenberg/vm2/common/to_radix.hpp" +#include "barretenberg/vm2/tracegen/lib/lookup_builder.hpp" + +namespace bb::avm2::tracegen { + +template class LookupIntoPDecomposition : public BaseLookupTraceBuilder { + private: + uint32_t find_in_dst(const std::array& tup) const override + { + const auto& [radix, limb_index, _] = tup; + size_t radix_index = static_cast(radix); + uint32_t row = 0; + for (size_t i = 0; i < radix_index; ++i) { + row += static_cast(get_p_limbs_per_radix()[i].size()); + } + + row += static_cast(limb_index); + + return row; + } +}; + +} // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp index a1dab47e3891..fd0f44de96c2 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp @@ -6,6 +6,7 @@ #include "barretenberg/vm2/common/instruction_spec.hpp" #include "barretenberg/vm2/common/memory_types.hpp" +#include "barretenberg/vm2/common/to_radix.hpp" namespace bb::avm2::tracegen { @@ -212,4 +213,41 @@ void PrecomputedTraceBuilder::process_wire_instruction_spec(TraceContainer& trac } } +void PrecomputedTraceBuilder::process_to_radix_safe_limbs(TraceContainer& trace) +{ + using C = Column; + + auto p_limbs_per_radix = get_p_limbs_per_radix(); + + trace.reserve_column(C::precomputed_sel_to_radix_safe_limbs, p_limbs_per_radix.size()); + trace.reserve_column(C::precomputed_to_radix_safe_limbs, p_limbs_per_radix.size()); + + for (size_t i = 0; i < p_limbs_per_radix.size(); ++i) { + size_t decomposition_len = p_limbs_per_radix[i].size(); + if (decomposition_len > 0) { + trace.set(C::precomputed_sel_to_radix_safe_limbs, static_cast(i), 1); + trace.set(C::precomputed_to_radix_safe_limbs, static_cast(i), decomposition_len - 1); + } + } +} + +void PrecomputedTraceBuilder::process_to_radix_p_decompositions(TraceContainer& trace) +{ + using C = Column; + + auto p_limbs_per_radix = get_p_limbs_per_radix(); + + uint32_t row = 0; + for (size_t i = 0; i < p_limbs_per_radix.size(); ++i) { + size_t decomposition_len = p_limbs_per_radix[i].size(); + for (size_t j = 0; j < decomposition_len; ++j) { + trace.set(C::precomputed_sel_p_decomposition, row, 1); + trace.set(C::precomputed_p_decomposition_radix, row, i); + trace.set(C::precomputed_p_decomposition_limb_index, row, j); + trace.set(C::precomputed_p_decomposition_limb, row, p_limbs_per_radix[i][j]); + row++; + } + } +} + } // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp index 91f6cccf2392..cd97393f2050 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp @@ -19,6 +19,8 @@ class PrecomputedTraceBuilder final { void process_sha256_round_constants(TraceContainer& trace); void process_integral_tag_length(TraceContainer& trace); void process_wire_instruction_spec(TraceContainer& trace); + void process_to_radix_safe_limbs(TraceContainer& trace); + void process_to_radix_p_decompositions(TraceContainer& trace); }; } // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/to_radix_trace.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/to_radix_trace.cpp new file mode 100644 index 000000000000..c7c70c399f04 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/to_radix_trace.cpp @@ -0,0 +1,88 @@ +#include "barretenberg/vm2/tracegen/to_radix_trace.hpp" + +#include + +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/vm2/common/aztec_types.hpp" +#include "barretenberg/vm2/common/to_radix.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" +#include "barretenberg/vm2/simulation/events/to_radix_event.hpp" + +namespace bb::avm2::tracegen { + +void ToRadixTraceBuilder::process(const simulation::EventEmitterInterface::Container& events, + TraceContainer& trace) +{ + using C = Column; + + auto p_limbs_per_radix = get_p_limbs_per_radix(); + + uint32_t row = 1; // We start from row 1 because this trace contains shifted columns. + for (const auto& event : events) { + FF value = event.value; + uint32_t radix = event.radix; + size_t radix_index = static_cast(radix); + uint32_t safe_limbs = static_cast(p_limbs_per_radix[radix_index].size()) - 1; + + FF acc = 0; + FF exponent = 1; + bool found = false; + bool acc_under_p = false; + + for (uint32_t i = 0; i < event.limbs.size(); ++i) { + bool is_padding = i > safe_limbs; + uint8_t limb = event.limbs[i]; + uint8_t p_limb = is_padding ? 0 : p_limbs_per_radix[radix_index][static_cast(i)]; + + if (limb != p_limb) { + acc_under_p = limb < p_limb; + } + FF limb_p_diff = limb == p_limb ? 0 : limb > p_limb ? limb - p_limb - 1 : p_limb - limb - 1; + + bool is_unsafe_limb = i == safe_limbs; + FF safety_diff_inverse = is_unsafe_limb ? FF(0) : (FF(i) - FF(safe_limbs)).invert(); + + acc += exponent * limb; + + FF rem = value - acc; + found = rem == 0; + FF rem_inverse = found ? 0 : rem.invert(); + + bool end = i == (event.limbs.size() - 1); + + trace.set(row, + { { + { C::to_radix_sel, 1 }, + { C::to_radix_value, value }, + { C::to_radix_radix, radix }, + { C::to_radix_limb_index, i }, + { C::to_radix_limb, limb }, + { C::to_radix_start, i == 0 }, + { C::to_radix_end, end }, + { C::to_radix_not_end, !end }, + { C::to_radix_exponent, exponent }, + { C::to_radix_not_padding_limb, !is_padding }, + { C::to_radix_acc, acc }, + { C::to_radix_found, found }, + { C::to_radix_limb_radix_diff, radix - 1 - limb }, + { C::to_radix_rem_inverse, rem_inverse }, + { C::to_radix_safe_limbs, safe_limbs }, + { C::to_radix_is_unsafe_limb, is_unsafe_limb }, + { C::to_radix_safety_diff_inverse, safety_diff_inverse }, + { C::to_radix_p_limb, p_limb }, + { C::to_radix_acc_under_p, acc_under_p }, + { C::to_radix_limb_lt_p, limb < p_limb }, + { C::to_radix_limb_eq_p, limb == p_limb }, + { C::to_radix_limb_p_diff, limb_p_diff }, + } }); + + row++; + if (is_unsafe_limb) { + exponent = 0; + } + exponent *= radix; + } + } +} + +} // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/to_radix_trace.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/to_radix_trace.hpp new file mode 100644 index 000000000000..16d5dd5c5502 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/to_radix_trace.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "barretenberg/vm2/generated/columns.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" +#include "barretenberg/vm2/simulation/events/to_radix_event.hpp" +#include "barretenberg/vm2/tracegen/trace_container.hpp" + +namespace bb::avm2::tracegen { + +class ToRadixTraceBuilder final { + public: + void process(const simulation::EventEmitterInterface::Container& events, + TraceContainer& trace); +}; + +} // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp index f32947cb32a9..cb844400f45d 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp @@ -21,7 +21,9 @@ #include "barretenberg/vm2/generated/relations/lookups_instr_fetching.hpp" #include "barretenberg/vm2/generated/relations/lookups_poseidon2_hash.hpp" #include "barretenberg/vm2/generated/relations/lookups_range_check.hpp" +#include "barretenberg/vm2/generated/relations/lookups_scalar_mul.hpp" #include "barretenberg/vm2/generated/relations/lookups_sha256.hpp" +#include "barretenberg/vm2/generated/relations/lookups_to_radix.hpp" #include "barretenberg/vm2/tracegen/alu_trace.hpp" #include "barretenberg/vm2/tracegen/bytecode_trace.hpp" #include "barretenberg/vm2/tracegen/class_id_derivation_trace.hpp" @@ -31,10 +33,12 @@ #include "barretenberg/vm2/tracegen/lib/lookup_builder.hpp" #include "barretenberg/vm2/tracegen/lib/lookup_into_bitwise.hpp" #include "barretenberg/vm2/tracegen/lib/lookup_into_indexed_by_clk.hpp" +#include "barretenberg/vm2/tracegen/lib/lookup_into_p_decomposition.hpp" #include "barretenberg/vm2/tracegen/lib/permutation_builder.hpp" #include "barretenberg/vm2/tracegen/poseidon2_trace.hpp" #include "barretenberg/vm2/tracegen/precomputed_trace.hpp" #include "barretenberg/vm2/tracegen/sha256_trace.hpp" +#include "barretenberg/vm2/tracegen/to_radix_trace.hpp" #include "barretenberg/vm2/tracegen/trace_container.hpp" namespace bb::avm2 { @@ -67,6 +71,10 @@ auto build_precomputed_columns_jobs(TraceContainer& trace) precomputed_builder.process_integral_tag_length(trace)); AVM_TRACK_TIME("tracegen/precomputed/operand_dec_selectors", precomputed_builder.process_wire_instruction_spec(trace)); + AVM_TRACK_TIME("tracegen/precomputed/to_radix_safe_limbs", + precomputed_builder.process_to_radix_safe_limbs(trace)); + AVM_TRACK_TIME("tracegen/precomputed/to_radix_p_decompositions", + precomputed_builder.process_to_radix_p_decompositions(trace)); }, }; } @@ -227,7 +235,13 @@ TraceContainer AvmTraceGenHelper::generate_trace(EventsContainer&& events) AVM_TRACK_TIME("tracegen/poseidon2_permutation", poseidon2_builder.process_permutation(events.poseidon2_permutation, trace)); clear_events(events.poseidon2_permutation); - } }); + }, + [&]() { + ToRadixTraceBuilder to_radix_builder; + AVM_TRACK_TIME("tracegen/to_radix", to_radix_builder.process(events.to_radix, trace)); + clear_events(events.to_radix); + }, + }); AVM_TRACK_TIME("tracegen/traces", execute_jobs(jobs)); } @@ -267,7 +281,14 @@ TraceContainer AvmTraceGenHelper::generate_trace(EventsContainer&& events) LookupIntoDynamicTableSequential>(), // Scalar mul std::make_unique>(), - std::make_unique>()); + std::make_unique>(), + std::make_unique>(), + // To radix + std::make_unique>(), + std::make_unique>(), + std::make_unique>(), + std::make_unique>(), + std::make_unique>()); AVM_TRACK_TIME("tracegen/interactions", parallel_for(jobs_interactions.size(), [&](size_t i) { jobs_interactions[i]->process(trace); }));