@@ -16,31 +16,36 @@ using namespace numeric;
1616
1717namespace {
1818/* *
19- * @brief Find the position of the highest set bit in a uint128_t
20- * @return -1 if no bits are set, otherwise the bit position (0-127 )
19+ * @brief Find the position of the highest set bit in a uint256_t
20+ * @return -1 if no bits are set, otherwise the bit position (0-255 )
2121 */
22- inline int highest_set_bit_128 ( uint128_t value)
22+ inline int highest_set_bit_256 ( uint256_t value)
2323{
2424 if (value == 0 ) {
2525 return -1 ;
2626 }
27- // Check high 64 bits first
28- auto high = static_cast <uint64_t >(value >> 64 );
29- if (high != 0 ) {
30- return 127 - __builtin_clzll (high);
27+ // Check high bits first, then go down
28+ for (int idx = 0 ; idx < 3 ; idx++) {
29+ auto chunk = static_cast <uint64_t >(value >> 64 * (3 - idx));
30+ if (chunk != 0 ) {
31+ return 255 - (idx * 64 ) - __builtin_clzll (chunk);
32+ }
3133 }
32- // Check low 64 bits
33- auto low = static_cast <uint64_t >(value);
34- return 63 - __builtin_clzll (low);
34+
35+ // Lowest bits
36+ auto chunk = static_cast <uint64_t >(value);
37+ return 63 - __builtin_clzll (chunk);
3538}
3639
3740/* *
38- * @brief Safely extract uint128_t from uint256_t data array using memcpy to avoid strict aliasing issues
41+ * @brief Safely extract uint256_t from uint512_t data array using memcpy to avoid strict aliasing issues
3942 */
40- inline uint128_t extract_uint128 (const uint64_t * data)
43+ inline uint256_t extract_uint256 (const uint256_t & data)
4144{
42- uint128_t result = 0 ;
43- std::memcpy (&result, data, sizeof (uint128_t ));
45+ uint256_t result = 0 ;
46+ for (size_t idx = 0 ; idx < 4 ; ++idx) {
47+ std::memcpy (&result.data [idx], &data.data [idx], sizeof (uint64_t ));
48+ }
4449 return result;
4550}
4651} // namespace
@@ -60,22 +65,22 @@ inline uint128_t extract_uint128(const uint64_t* data)
6065 * @param provenance_a Round provenance of first element
6166 * @param provenance_b Round provenance of second element
6267 */
63- void check_round_provenance (const uint256_t & provenance_a, const uint256_t & provenance_b)
68+ void check_round_provenance (const uint512_t & provenance_a, const uint512_t & provenance_b)
6469{
65- // Lower 128 bits = submitted rounds, Upper 128 bits = challenge rounds
66- const auto submitted_a = extract_uint128 (& provenance_a.data [ 0 ] );
67- const auto submitted_b = extract_uint128 (& provenance_b.data [ 0 ] );
70+ // Lower 256 bits = submitted rounds, Upper 256 bits = challenge rounds
71+ const auto submitted_a = extract_uint256 ( provenance_a.lo );
72+ const auto submitted_b = extract_uint256 ( provenance_b.lo );
6873
6974 // Nothing to check if either has no submitted data or both are from the same round(s)
7075 if (submitted_a == 0 || submitted_b == 0 || submitted_a == submitted_b) {
7176 return ;
7277 }
7378
7479 // Ensure that values from different rounds are not mixing without max challenge round >= max submitted round
75- const auto challenges_a = extract_uint128 (& provenance_a.data [ 2 ] );
76- const auto challenges_b = extract_uint128 (& provenance_b.data [ 2 ] );
77- const int max_challenge_round = highest_set_bit_128 (challenges_a | challenges_b);
78- const int max_submitted_round = highest_set_bit_128 (submitted_a | submitted_b);
80+ const auto challenges_a = extract_uint256 ( provenance_a.hi );
81+ const auto challenges_b = extract_uint256 ( provenance_b.hi );
82+ const int max_challenge_round = highest_set_bit_256 (challenges_a | challenges_b);
83+ const int max_submitted_round = highest_set_bit_256 (submitted_a | submitted_b);
7984
8085 if (max_challenge_round < max_submitted_round) {
8186 throw_or_abort (" Round provenance check failed: max challenge round (" + std::to_string (max_challenge_round) +
@@ -92,8 +97,7 @@ OriginTag::OriginTag(const OriginTag& tag_a, const OriginTag& tag_b)
9297{
9398 // Elements with instant death should not be touched
9499 if (tag_a.instant_death || tag_b.instant_death ) {
95- throw_or_abort (" Touched an element that should not have been touched. tag_a id: " +
96- std::to_string (tag_a.tag_id ) + " , tag_b id: " + std::to_string (tag_b.tag_id ));
100+ throw_or_abort (" Touched an element that should not have been touched" );
97101 }
98102 // If one of the tags is a constant, just use the other tag
99103 if (tag_a.transcript_index == CONSTANT ) {
@@ -108,9 +112,7 @@ OriginTag::OriginTag(const OriginTag& tag_a, const OriginTag& tag_b)
108112 // A free witness element should not interact with an element that has an origin
109113 if (tag_a.is_free_witness ()) {
110114 if (!tag_b.is_free_witness () && !tag_b.is_empty ()) {
111- throw_or_abort (
112- " A free witness element (id: " + std::to_string (tag_a.tag_id ) +
113- " ) should not interact with an element that has an origin (id: " + std::to_string (tag_b.tag_id ) + " )" );
115+ throw_or_abort (" A free witness element should not interact with an element that has an origin" );
114116 } else {
115117 // If both are free witnesses or one of them is empty, just use tag_a
116118 *this = tag_a;
@@ -119,9 +121,7 @@ OriginTag::OriginTag(const OriginTag& tag_a, const OriginTag& tag_b)
119121 }
120122 if (tag_b.is_free_witness ()) {
121123 if (!tag_a.is_free_witness () && !tag_a.is_empty ()) {
122- throw_or_abort (
123- " A free witness element (id: " + std::to_string (tag_b.tag_id ) +
124- " ) should not interact with an element that has an origin (id: " + std::to_string (tag_a.tag_id ) + " )" );
124+ throw_or_abort (" A free witness element should not interact with an element that has an origin" );
125125 } else {
126126 // If both are free witnesses or one of them is empty, just use tag_b
127127 *this = tag_b;
@@ -130,10 +130,7 @@ OriginTag::OriginTag(const OriginTag& tag_a, const OriginTag& tag_b)
130130 }
131131 // Elements from different transcripts shouldn't interact
132132 if (tag_a.transcript_index != tag_b.transcript_index ) {
133- throw_or_abort (" Tags from different transcripts were involved in the same computation. tag_a: { id: " +
134- std::to_string (tag_a.tag_id ) + " , transcript: " + std::to_string (tag_a.transcript_index ) +
135- " } tag_b: { id: " + std::to_string (tag_b.tag_id ) +
136- " , transcript: " + std::to_string (tag_b.transcript_index ) + " }" );
133+ throw_or_abort (" Tags from different transcripts were involved in the same computation" );
137134 }
138135 // Check that submitted values from different rounds don't mix without challenges
139136 check_round_provenance (tag_a.round_provenance , tag_b.round_provenance );
0 commit comments