Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bigfield.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
9#include "../byte_array/byte_array.hpp"
10#include "../circuit_builders/circuit_builders_fwd.hpp"
11#include "../field/field.hpp"
18
19namespace bb::stdlib {
20
21template <typename Builder, typename T> class bigfield {
22
23 public:
24 using View = bigfield;
26 using TParams = T;
29
30 // Number of bb::fr field elements used to represent a bigfield element in the public inputs
31 static constexpr size_t PUBLIC_INPUTS_SIZE = BIGFIELD_PUBLIC_INPUTS_SIZE;
32
33 struct Basis {
35 size_t num_bits;
36 };
37
44 struct Limb {
45 Limb() = default;
47 : element(input)
48 {
49 if (input.is_constant()) {
52 } else {
53 maximum_value = max;
54 }
55 }
56 friend std::ostream& operator<<(std::ostream& os, const Limb& a)
57 {
58 os << "{ " << a.element << " <= " << a.maximum_value << " }";
59 return os;
60 }
61 Limb(const Limb& other) = default;
62 Limb(Limb&& other) noexcept = default;
63 Limb& operator=(const Limb& other) = default;
64 Limb& operator=(Limb&& other) noexcept = default;
65 ~Limb() = default;
66
69 };
70
71 // Number of limbs used to represent a bigfield element in the binary basis
72 static constexpr size_t NUM_LIMBS = 4;
73
75
81
86
96 bigfield(const field_t<Builder>& low_bits,
97 const field_t<Builder>& high_bits,
98 const bool can_overflow = false,
99 const size_t maximum_bitlength = 0);
100
107 bigfield(Builder* parent_context = nullptr);
108
115 bigfield(Builder* parent_context, const uint256_t& value);
116
117 explicit bigfield(const uint256_t& value)
118 : bigfield(nullptr, uint256_t(value))
119 {}
120
126 bigfield(const int value)
127 : bigfield(nullptr, uint256_t(native(value)))
128 {}
129
130 // NOLINTNEXTLINE(google-runtime-int) intended behavior
131 bigfield(const unsigned long value)
132 : bigfield(nullptr, value)
133 {}
134
135 // NOLINTNEXTLINE(google-runtime-int) intended behavior
136 bigfield(const unsigned long long value)
137 : bigfield(nullptr, value)
138 {}
139
147 : bigfield(nullptr, uint256_t(value))
148 {}
149
158 const field_t<Builder>& b,
159 const field_t<Builder>& c,
160 const field_t<Builder>& d,
161 const bool can_overflow = false)
162 {
163 BB_ASSERT_EQ(a.is_constant(), b.is_constant());
164 BB_ASSERT_EQ(b.is_constant(), c.is_constant());
166 bigfield result;
167 result.context = a.context;
168 result.binary_basis_limbs[0] = Limb(field_t(a));
169 result.binary_basis_limbs[1] = Limb(field_t(b));
170 result.binary_basis_limbs[2] = Limb(field_t(c));
171 result.binary_basis_limbs[3] =
173 result.prime_basis_limb = (result.binary_basis_limbs[3].element * shift_3)
174 .add_two(result.binary_basis_limbs[2].element * shift_2,
175 result.binary_basis_limbs[1].element * shift_1);
176 result.prime_basis_limb += (result.binary_basis_limbs[0].element);
177 return result;
178 };
179
186 const field_t<Builder>& b,
187 const field_t<Builder>& c,
188 const field_t<Builder>& d,
189 const bool can_overflow = false)
190 {
191 BB_ASSERT_EQ(a.is_constant(), b.is_constant());
192 BB_ASSERT_EQ(b.is_constant(), c.is_constant());
194 bigfield result;
195 auto ctx = a.context;
196 result.context = a.context;
197 result.binary_basis_limbs[0] = Limb(field_t(a));
198 result.binary_basis_limbs[1] = Limb(field_t(b));
199 result.binary_basis_limbs[2] = Limb(field_t(c));
200 result.binary_basis_limbs[3] =
202 result.prime_basis_limb = (result.binary_basis_limbs[3].element * shift_3)
203 .add_two(result.binary_basis_limbs[2].element * shift_2,
204 result.binary_basis_limbs[1].element * shift_1);
205 result.prime_basis_limb += (result.binary_basis_limbs[0].element);
206
207 // Range contrain the first two limbs each to NUM_LIMB_BITS
208 ctx->range_constrain_two_limbs(result.binary_basis_limbs[0].element.get_witness_index(),
209 result.binary_basis_limbs[1].element.get_witness_index(),
210 static_cast<size_t>(NUM_LIMB_BITS),
211 static_cast<size_t>(NUM_LIMB_BITS),
212 "bigfield::construct_from_limbs: limb 0 or 1 too large");
213
214 // Range constrain the last two limbs to NUM_LIMB_BITS and NUM_LAST_LIMB_BITS
215 const size_t num_last_limb_bits = (can_overflow) ? NUM_LIMB_BITS : NUM_LAST_LIMB_BITS;
216 ctx->range_constrain_two_limbs(result.binary_basis_limbs[2].element.get_witness_index(),
217 result.binary_basis_limbs[3].element.get_witness_index(),
218 static_cast<size_t>(NUM_LIMB_BITS),
219 static_cast<size_t>(num_last_limb_bits),
220 "bigfield::construct_from_limbs: limb 2 or 3 too large");
221
222 return result;
223 };
224
233 const field_t<Builder>& b,
234 const field_t<Builder>& c,
235 const field_t<Builder>& d,
236 const field_t<Builder>& prime_limb,
237 const bool can_overflow = false)
238 {
239 BB_ASSERT_EQ(a.is_constant(), b.is_constant());
240 BB_ASSERT_EQ(b.is_constant(), c.is_constant());
242 BB_ASSERT_EQ(d.is_constant(), prime_limb.is_constant());
243 bigfield result;
244 result.context = a.context;
245 result.binary_basis_limbs[0] = Limb(field_t(a));
246 result.binary_basis_limbs[1] = Limb(field_t(b));
247 result.binary_basis_limbs[2] = Limb(field_t(c));
248 result.binary_basis_limbs[3] =
250 result.prime_basis_limb = prime_limb;
251 return result;
252 };
253
267 bigfield(const byte_array<Builder>& bytes);
268
269 // Copy constructor
270 bigfield(const bigfield& other);
271
272 // Move constructor
273 bigfield(bigfield&& other) noexcept;
274
275 // Destructor
276 ~bigfield() = default;
277
292 const uint512_t& value,
293 const bool can_overflow = false,
294 const size_t maximum_bitlength = 0);
295
296 static bigfield from_witness(Builder* ctx, const bb::field<T>& input)
297 {
298 uint256_t input_u256(input);
299 field_t<Builder> low(witness_t<Builder>(ctx, bb::fr(input_u256.slice(0, NUM_LIMB_BITS * 2))));
301 auto result = bigfield(low, hi);
302 result.set_free_witness_tag();
303 return result;
304 }
305
306 // Disallow from_witness for non-bb::fr types to prevent implicit conversions (specifically, using indices rather
307 // than values)
308 template <typename OT> static bigfield from_witness(Builder* ctx, const OT& input) = delete;
309
310 bigfield& operator=(const bigfield& other);
311 bigfield& operator=(bigfield&& other) noexcept;
312
313 // Code assumes modulus is at most 256 bits so good to define it via a uint256_t
314 static constexpr uint256_t modulus = (uint256_t(T::modulus_0, T::modulus_1, T::modulus_2, T::modulus_3));
315 static constexpr uint512_t modulus_u512 = static_cast<uint512_t>(modulus);
316 static constexpr uint64_t NUM_LIMB_BITS = NUM_LIMB_BITS_IN_FIELD_SIMULATION;
317 static constexpr uint64_t NUM_LAST_LIMB_BITS = modulus_u512.get_msb() + 1 - (NUM_LIMB_BITS * 3);
318
319 // The quotient reduction checks currently only support >=250 bit moduli and moduli >256 have never been tested
320 // (Check zkSecurity audit report issue #12 for explanation)
321 static_assert(modulus_u512.get_msb() + 1 >= 250 && modulus_u512.get_msb() + 1 <= 256);
322
328 static constexpr uint64_t LOG2_BINARY_MODULUS = NUM_LIMB_BITS * NUM_LIMBS;
329 static constexpr bool is_composite = true; // false only when fr is native
330
331 // This limits the size of all vectors that are being used to 16 (we don't really need more)
332 static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG = 4;
333 static constexpr size_t MAXIMUM_SUMMAND_COUNT = 1 << MAXIMUM_SUMMAND_COUNT_LOG;
334
337 static constexpr Basis target_basis{ modulus_u512, static_cast<size_t>(modulus_u512.get_msb() + 1) };
338 static constexpr bb::fr shift_1 = bb::fr(uint256_t(1) << NUM_LIMB_BITS);
339 static constexpr bb::fr shift_2 = bb::fr(uint256_t(1) << (NUM_LIMB_BITS * 2));
340 static constexpr bb::fr shift_3 = bb::fr(uint256_t(1) << (NUM_LIMB_BITS * 3));
355
356 // Gets the integer (uint512_t) value of the bigfield element by combining the binary basis limbs.
357 uint512_t get_value() const;
358
359 // Gets the maximum value of the bigfield element by combining the maximum values of the binary basis limbs.
361
378 bigfield add_to_lower_limb(const field_t<Builder>& other, const uint256_t& other_maximum_value) const;
379
394 bigfield operator+(const bigfield& other) const;
395
407 bigfield add_two(const bigfield& add_a, const bigfield& add_b) const;
408
422 bigfield operator-(const bigfield& other) const;
423
437 bigfield operator*(const bigfield& other) const;
438
449 bigfield operator/(const bigfield& other) const;
450
456 bigfield operator-() const { return bigfield(get_context(), uint256_t(0)) - *this; }
457
459 {
460 *this = operator+(other);
461 return *this;
462 }
464 {
465 *this = operator-(other);
466 return *this;
467 }
469 {
470 *this = operator*(other);
471 return *this;
472 }
474 {
475 *this = operator/(other);
476 return *this;
477 }
478
487 bigfield sqr() const;
488
498 bigfield sqradd(const std::vector<bigfield>& to_add) const;
499
511 bigfield pow(const uint32_t exponent) const;
512
521 bigfield madd(const bigfield& to_mul, const std::vector<bigfield>& to_add) const;
522
524 std::vector<bigfield>& mul_right,
525 const std::vector<bigfield>& to_add);
526
527 static bigfield mult_madd(const std::vector<bigfield>& mul_left,
528 const std::vector<bigfield>& mul_right,
529 const std::vector<bigfield>& to_add,
530 bool fix_remainder_to_zero = false);
531
532 static bigfield dual_madd(const bigfield& left_a,
533 const bigfield& right_a,
534 const bigfield& left_b,
535 const bigfield& right_b,
536 const std::vector<bigfield>& to_add);
537
538 // compute -(mul_left * mul_right + ...to_sub) / (divisor)
539 // We can evaluate this relationship with only one set of quotient/remainder range checks
540 static bigfield msub_div(const std::vector<bigfield>& mul_left,
541 const std::vector<bigfield>& mul_right,
542 const bigfield& divisor,
543 const std::vector<bigfield>& to_sub,
544 bool enable_divisor_nz_check = true);
545
546 static bigfield sum(const std::vector<bigfield>& terms);
547 static bigfield internal_div(const std::vector<bigfield>& numerators,
548 const bigfield& denominator,
549 bool check_for_zero);
550
551 static bigfield div_without_denominator_check(const std::vector<bigfield>& numerators, const bigfield& denominator);
553 static bigfield div_check_denominator_nonzero(const std::vector<bigfield>& numerators, const bigfield& denominator);
554
555 bigfield conditional_negate(const bool_t<Builder>& predicate) const;
556
566 bigfield conditional_select(const bigfield& other, const bool_t<Builder>& predicate) const;
567 static bigfield conditional_assign(const bool_t<Builder>& predicate, const bigfield& lhs, const bigfield& rhs)
568 {
569 return rhs.conditional_select(lhs, predicate);
570 }
571
572 bool_t<Builder> operator==(const bigfield& other) const;
573
574 void assert_is_in_field(std::string const& msg = "bigfield::assert_is_in_field") const;
575 void assert_less_than(const uint256_t& upper_limit, std::string const& msg = "bigfield::assert_less_than") const;
576 void reduce_mod_target_modulus() const;
577 void assert_equal(const bigfield& other, std::string const& msg = "bigfield::assert_equal") const;
578 void assert_is_not_equal(const bigfield& other,
579 std::string const& msg = "bigfield: prime limb diff is zero, but expected non-zero") const;
580
590 void self_reduce() const;
591
599 bool is_constant() const
600 {
601 bool is_limb_0_constant = binary_basis_limbs[0].element.is_constant();
602 bool is_limb_1_constant = binary_basis_limbs[1].element.is_constant();
603 bool is_limb_2_constant = binary_basis_limbs[2].element.is_constant();
604 bool is_limb_3_constant = binary_basis_limbs[3].element.is_constant();
605 bool is_prime_limb_constant = prime_basis_limb.is_constant();
606 BB_ASSERT_EQ(is_limb_0_constant, is_limb_1_constant);
607 BB_ASSERT_EQ(is_limb_1_constant, is_limb_2_constant);
608 BB_ASSERT_EQ(is_limb_2_constant, is_limb_3_constant);
609 BB_ASSERT_EQ(is_limb_3_constant, is_prime_limb_constant);
610 return is_prime_limb_constant;
611 }
612
618 bigfield invert() const { return (bigfield(1) / bigfield(*this)); }
619
623 static bigfield one()
624 {
625 bigfield result(nullptr, uint256_t(1));
626 return result;
627 }
628
632 static bigfield zero()
633 {
634 bigfield result(nullptr, uint256_t(0));
635 return result;
636 }
637
644 static constexpr bigfield unreduced_zero()
645 {
646 uint512_t multiple_of_modulus = ((get_maximum_unreduced_value() / modulus_u512) + 1) * modulus_u512;
647 auto msb = multiple_of_modulus.get_msb();
648
649 bigfield result(nullptr, uint256_t(0));
650 result.binary_basis_limbs[0] = Limb(bb::fr(multiple_of_modulus.slice(0, NUM_LIMB_BITS).lo));
651 result.binary_basis_limbs[1] = Limb(bb::fr(multiple_of_modulus.slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS).lo));
652 result.binary_basis_limbs[2] = Limb(bb::fr(multiple_of_modulus.slice(2 * NUM_LIMB_BITS, 3 * NUM_LIMB_BITS).lo));
653 result.binary_basis_limbs[3] = Limb(bb::fr(multiple_of_modulus.slice(3 * NUM_LIMB_BITS, msb + 1).lo));
654 result.prime_basis_limb = field_t<Builder>((multiple_of_modulus % uint512_t(field_t<Builder>::modulus)).lo);
655 return result;
656 }
657
662 {
664 for (auto& limb : binary_basis_limbs) {
665 limb.element.convert_constant_to_fixed_witness(context);
666 }
668 }
669
674 {
675 // Origin tags should be updated within
676 for (auto& limb : binary_basis_limbs) {
677 limb.element.fix_witness();
678 }
680
681 // This is now effectively a constant
683 }
684
685 Builder* get_context() const { return context; }
686
688 {
689 for (size_t i = 0; i < NUM_LIMBS; i++) {
690 binary_basis_limbs[i].element.set_origin_tag(tag);
691 }
693 }
695 {
696 for (size_t i = 0; i < NUM_LIMBS; i++) {
697 binary_basis_limbs[i].element.clear_round_provenance();
698 }
700 }
701
703 {
705 binary_basis_limbs[1].element.tag,
706 binary_basis_limbs[2].element.tag,
707 binary_basis_limbs[3].element.tag,
709 }
710
715 {
716 for (auto& limb : binary_basis_limbs) {
717 limb.element.set_free_witness_tag();
718 }
720 }
721
726 {
727 for (auto& limb : binary_basis_limbs) {
728 limb.element.unset_free_witness_tag();
729 }
731 }
737 uint32_t set_public() const
738 {
739 Builder* ctx = get_context();
740 const uint32_t start_index = static_cast<uint32_t>(ctx->num_public_inputs());
741 for (auto& limb : binary_basis_limbs) {
742 ctx->set_public_input(limb.element.get_witness_index());
743 }
744 return start_index;
745 }
746
751 {
752 return construct_from_limbs(limbs[0], limbs[1], limbs[2], limbs[3], /*can_overflow=*/false);
753 }
754
756 {
757 // This = `T * n = 2^272 * |BN(Fr)|` So this equals n*2^t
758 uint1024_t maximum_product = get_maximum_crt_product();
759
760 // In multiplying two bigfield elements a and b, we must check that:
761 //
762 // a * b = q * p + r
763 //
764 // where q is the quotient, r is the remainder, and p is the size of the non-native field.
765 // The CRT requires that we check that the equation:
766 // (a) holds modulo the size of the native field n,
767 // (b) holds modulo the size of the bigger ring 2^t,
768 // (c) both sides of the equation are less than the max product M = 2^t * n.
769 // Thus, the max value of an unreduced bigfield element is √M. In this case, we use
770 // an even stricter bound. Let n = 2^m + l (where 1 < l < 2^m). Thus, we have:
771 //
772 // M = 2^t * n = 2^t * (2^m + l) = 2^(t + m) + (2^t * l)
773 // => M > 2^(t + m)
774 // => √M > 2^((t + m) / 2)
775 //
776 // We set the maximum unreduced value of a bigfield element to be: 2^((t + m) / 2) < √M.
777 //
778 // Note: We use a further safer bound of 2^((t + m - 1) / 2). We use -1 to stay safer,
779 // because it provides additional space to avoid the overflow, but get_msb() by itself should be enough.
780 uint64_t maximum_product_bits = maximum_product.get_msb() - 1;
781 return (uint512_t(1) << (maximum_product_bits >> 1)) - uint512_t(1);
782 }
783
784 // If we encounter this maximum value of a bigfield we stop execution
786 {
787 uint1024_t maximum_product = get_maximum_crt_product();
788 uint64_t maximum_product_bits = maximum_product.get_msb() - 1;
789 const size_t arbitrary_secure_margin = 20;
790 return (uint512_t(1) << ((maximum_product_bits >> 1) + arbitrary_secure_margin)) - uint512_t(1);
791 }
792
803 {
805 return maximum_product;
806 }
807
818 static size_t get_quotient_max_bits(const std::vector<uint1024_t>& remainders_max)
819 {
820 // find q_max * p + ...remainders_max < nT
822 for (const auto& r : remainders_max) {
823 base -= r;
824 }
825 base /= modulus_u512;
826 return static_cast<size_t>(base.get_msb() - 1);
827 }
828
839 const uint1024_t& b_max,
840 const std::vector<bigfield>& to_add)
841 {
842 uint1024_t product = a_max * b_max;
843 uint1024_t add_term = 0;
844 for (const auto& add : to_add) {
845 add_term += add.get_maximum_value();
846 }
847 constexpr uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
848
849 // check that the add terms alone cannot overflow the crt modulus. v. unlikely so just forbid circuits that
850 // trigger this case
851 BB_ASSERT_LT(add_term + maximum_default_bigint, get_maximum_crt_product());
852 return ((product + add_term) >= get_maximum_crt_product());
853 }
854
865 const std::vector<uint512_t>& bs_max,
866 const std::vector<bigfield>& to_add)
867 {
869 BB_ASSERT_EQ(as_max.size(), bs_max.size());
870 // Computing individual products
871 uint1024_t product_sum = 0;
872 uint1024_t add_term = 0;
873 for (size_t i = 0; i < as_max.size(); i++) {
874 product_sum += uint1024_t(as_max[i]) * uint1024_t(bs_max[i]);
875 }
876 for (const auto& add : to_add) {
877 add_term += add.get_maximum_value();
878 }
879 static const uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
880
881 // check that the add terms alone cannot overflow the crt modulus. v. unlikely so just forbid circuits that
882 // trigger this case
883 BB_ASSERT_LT(add_term + maximum_default_bigint, get_maximum_crt_product());
884 return ((product_sum + add_term) >= get_maximum_crt_product());
885 }
886
887 // a (currently generous) upper bound on the log of number of fr additions in any of the class operations
888 static constexpr uint64_t MAX_ADDITION_LOG = 10;
889
890 // The rationale of the expression is we should not overflow Fr when applying any bigfield operation (e.g. *) and
891 // starting with this max limb size
892 //
893 // In multiplication of bigfield elements a * b, we encounter sum of limbs multiplications of form:
894 // c0 := a0 * b0
895 // c1 := a1 * b0 + a0 * b1
896 // c2 := a2 * b0 + a1 * b1 + a0 * b2
897 // c3 := a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
898 // output:
899 // lo := c0 + c1 * 2^L,
900 // hi := c2 + c3 * 2^L.
901 // Since hi term contains upto 4 limb-products, we must ensure that the hi term does not overflow the native field
902 // modulus. Suppose we are adding 2^k such terms. Let Q be the max bitsize of a limb. We want to ensure that the sum
903 // doesn't overflow the native field modulus. Hence:
904 // max(∑ hi) = max(∑ c2 + c3 * 2^L)
905 // = max(∑ c2) + max(∑ c3 * 2^L)
906 // = 2^k * (3 * 2^2Q) + 2^k * 2^L * (4 * 2^2Q)
907 // < 2^k * (2^L + 1) * (4 * 2^2Q)
908 // < n
909 // ==> 2^k * 2^L * 2^(2Q + 3) < n
910 // ==> 2Q + 3 < (log(n) - k - L)
911 // ==> Q < ((log(n) - k - L) - 3) / 2
912 //
913 static constexpr uint64_t MAXIMUM_LIMB_SIZE_THAT_WOULDNT_OVERFLOW =
915
916 // If the logarithm of the maximum value of a limb is more than this, we need to reduce.
917 // We allow an element to be added to itself 10 times, so we allow the limb to grow by 10 bits.
918 // Number 10 is arbitrary, there's no actual usecase for adding 1024 elements together.
920
921 // If we reach this size of a limb, we stop execution (as safety measure). This should never reach during addition
922 // as we would reduce the limbs before they reach this size.
923 static constexpr uint64_t PROHIBITED_LIMB_BITS = MAX_UNREDUCED_LIMB_BITS + 5;
924
925 // If we encounter this maximum value of a bigfield we need to reduce it.
927 {
928 return ((uint256_t(1) << MAX_UNREDUCED_LIMB_BITS) - uint256_t(1));
929 }
930
931 // If we encounter this maximum value of a limb we stop execution
933
935
936 // For testing purposes only
938
939 private:
946 void unsafe_assert_less_than(const uint256_t& upper_limit,
947 std::string const& msg = "bigfield::unsafe_assert_less_than") const;
948
955 {
956 std::array<uint32_t, NUM_LIMBS> limb_witness_indices;
957 for (size_t i = 0; i < NUM_LIMBS; i++) {
958 limb_witness_indices[i] = binary_basis_limbs[i].element.get_witness_index();
959 }
960 return limb_witness_indices;
961 }
962
974 static std::array<uint32_t, 2> decompose_non_native_field_double_width_limb(
975 Builder* ctx, const uint32_t limb_idx, const size_t num_limb_bits = (2 * NUM_LIMB_BITS));
976
986 const bigfield& b,
987 const std::vector<bigfield>& to_add);
997 const std::vector<uint512_t>& bs,
998 const std::vector<uint512_t>& to_add);
999
1011 const std::vector<uint512_t>& bs_max,
1012 const std::vector<bigfield>& to_add,
1013 const std::vector<uint1024_t>& remainders_max = {
1015
1035 static void unsafe_evaluate_multiply_add(const bigfield& input_left,
1036 const bigfield& input_to_mul,
1037 const std::vector<bigfield>& to_add,
1038 const bigfield& input_quotient,
1039 const std::vector<bigfield>& input_remainders);
1040
1061 const std::vector<bigfield>& input_right,
1062 const std::vector<bigfield>& to_add,
1063 const bigfield& input_quotient,
1064 const std::vector<bigfield>& input_remainders);
1065
1080 static void unsafe_evaluate_square_add(const bigfield& left,
1081 const std::vector<bigfield>& to_add,
1082 const bigfield& quotient,
1083 const bigfield& remainder);
1084
1105 void reduction_check() const;
1106
1113 void sanity_check() const;
1114
1121 {
1123 for (size_t i = 0; i < NUM_LIMBS; i++) {
1124 limb_maximums[i] = binary_basis_limbs[i].maximum_value;
1125 }
1126 return limb_maximums;
1127 }
1128
1143
1144}; // namespace stdlib
1145
1146// NOTE: For testing private functions in bigfield
1148 public:
1149 template <typename bigfield>
1150 static void unsafe_assert_less_than(const bigfield& input, const uint256_t& upper_limit)
1151 {
1152 input.unsafe_assert_less_than(upper_limit);
1153 }
1154
1155 template <typename bigfield>
1156 static void unsafe_evaluate_multiply_add(const bigfield& input_left,
1157 const bigfield& input_to_mul,
1158 const std::vector<bigfield>& to_add,
1159 const bigfield& input_quotient,
1160 const std::vector<bigfield>& input_remainders)
1161 {
1162 bigfield::unsafe_evaluate_multiply_add(input_left, input_to_mul, to_add, input_quotient, input_remainders);
1163 }
1164
1165 template <typename bigfield>
1167 const std::vector<bigfield>& input_right,
1168 const std::vector<bigfield>& to_add,
1169 const bigfield& input_quotient,
1170 const std::vector<bigfield>& input_remainders)
1171 {
1173 input_left, input_right, to_add, input_quotient, input_remainders);
1174 }
1175};
1176
1177template <typename C, typename T> inline std::ostream& operator<<(std::ostream& os, bigfield<T, C> const& v)
1178{
1179 return os << v.get_value();
1180}
1181
1182} // namespace bb::stdlib
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:152
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:137
constexpr uint256_t slice(uint64_t start, uint64_t end) const
constexpr uint64_t get_msb() const
constexpr uintx slice(const uint64_t start, const uint64_t end) const
Definition uintx.hpp:82
constexpr uint64_t get_msb() const
Definition uintx.hpp:69
static void unsafe_evaluate_multiple_multiply_add(const std::vector< bigfield > &input_left, const std::vector< bigfield > &input_right, const std::vector< bigfield > &to_add, const bigfield &input_quotient, const std::vector< bigfield > &input_remainders)
static void unsafe_evaluate_multiply_add(const bigfield &input_left, const bigfield &input_to_mul, const std::vector< bigfield > &to_add, const bigfield &input_quotient, const std::vector< bigfield > &input_remainders)
static void unsafe_assert_less_than(const bigfield &input, const uint256_t &upper_limit)
static bigfield zero()
Definition bigfield.hpp:632
static constexpr uint256_t DEFAULT_MAXIMUM_MOST_SIGNIFICANT_LIMB
Definition bigfield.hpp:326
static size_t get_quotient_max_bits(const std::vector< uint1024_t > &remainders_max)
Compute the maximum number of bits for quotient range proof to protect against CRT underflow.
Definition bigfield.hpp:818
static bigfield unsafe_construct_from_limbs(const field_t< Builder > &a, const field_t< Builder > &b, const field_t< Builder > &c, const field_t< Builder > &d, const field_t< Builder > &prime_limb, const bool can_overflow=false)
Construct a bigfield element from binary limbs and a prime basis limb that are already reduced.
Definition bigfield.hpp:232
static constexpr uint512_t get_maximum_unreduced_value()
Definition bigfield.hpp:755
static constexpr uint256_t get_prohibited_limb_value()
Definition bigfield.hpp:932
static constexpr uint64_t NUM_LIMB_BITS
Definition bigfield.hpp:316
static constexpr Basis binary_basis
Definition bigfield.hpp:336
static void unsafe_evaluate_multiple_multiply_add(const std::vector< bigfield > &input_left, const std::vector< bigfield > &input_right, const std::vector< bigfield > &to_add, const bigfield &input_quotient, const std::vector< bigfield > &input_remainders)
Evaluate a relation involving multiple multiplications and additions.
static constexpr uint64_t MAX_ADDITION_LOG
Definition bigfield.hpp:888
static bigfield conditional_assign(const bool_t< Builder > &predicate, const bigfield &lhs, const bigfield &rhs)
Definition bigfield.hpp:567
static constexpr uint64_t MAX_UNREDUCED_LIMB_BITS
Definition bigfield.hpp:919
static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG
Definition bigfield.hpp:332
static bool mul_product_overflows_crt_modulus(const uint1024_t &a_max, const uint1024_t &b_max, const std::vector< bigfield > &to_add)
Definition bigfield.hpp:838
static bigfield msub_div(const std::vector< bigfield > &mul_left, const std::vector< bigfield > &mul_right, const bigfield &divisor, const std::vector< bigfield > &to_sub, bool enable_divisor_nz_check=true)
void clear_round_provenance() const
Definition bigfield.hpp:694
Builder * get_context() const
Definition bigfield.hpp:685
static constexpr uint1024_t get_maximum_crt_product()
Compute the maximum product of two bigfield elements in CRT: M = 2^t * n.
Definition bigfield.hpp:802
bigfield operator*(const bigfield &other) const
Evaluate a non-native field multiplication: (a * b = c mod p) where p == target_basis....
bigfield conditional_select(const bigfield &other, const bool_t< Builder > &predicate) const
Create an element which is equal to either this or other based on the predicate.
static bigfield div_check_denominator_nonzero(const std::vector< bigfield > &numerators, const bigfield &denominator)
static bigfield sum(const std::vector< bigfield > &terms)
Create constraints for summing these terms.
static void unsafe_evaluate_square_add(const bigfield &left, const std::vector< bigfield > &to_add, const bigfield &quotient, const bigfield &remainder)
Evaluate a square with several additions.
static constexpr uint64_t MAXIMUM_LIMB_SIZE_THAT_WOULDNT_OVERFLOW
Definition bigfield.hpp:913
static bigfield construct_from_limbs(const field_t< Builder > &a, const field_t< Builder > &b, const field_t< Builder > &c, const field_t< Builder > &d, const bool can_overflow=false)
Construct a bigfield element from binary limbs that are already reduced and ensure they are range con...
Definition bigfield.hpp:185
bigfield madd(const bigfield &to_mul, const std::vector< bigfield > &to_add) const
Compute a * b + ...to_add = c mod p.
bigfield conditional_negate(const bool_t< Builder > &predicate) const
static bigfield mult_madd(const std::vector< bigfield > &mul_left, const std::vector< bigfield > &mul_right, const std::vector< bigfield > &to_add, bool fix_remainder_to_zero=false)
void set_origin_tag(const bb::OriginTag &tag) const
Definition bigfield.hpp:687
uint512_t get_value() const
void assert_is_in_field(std::string const &msg="bigfield::assert_is_in_field") const
static bigfield internal_div(const std::vector< bigfield > &numerators, const bigfield &denominator, bool check_for_zero)
static constexpr std::array< bb::fr, NUM_LIMBS > neg_modulus_mod_binary_basis_limbs
Definition bigfield.hpp:349
void assert_less_than(const uint256_t &upper_limit, std::string const &msg="bigfield::assert_less_than") const
static constexpr size_t PUBLIC_INPUTS_SIZE
Definition bigfield.hpp:31
static constexpr Basis target_basis
Definition bigfield.hpp:337
static constexpr uint64_t PROHIBITED_LIMB_BITS
Definition bigfield.hpp:923
static constexpr Basis prime_basis
Definition bigfield.hpp:335
static const uint1024_t DEFAULT_MAXIMUM_REMAINDER
Definition bigfield.hpp:323
bigfield add_to_lower_limb(const field_t< Builder > &other, const uint256_t &other_maximum_value) const
Add a field element to the lower limb. CAUTION (the element has to be constrained before using this f...
bigfield(const native value)
Construct a new bigfield object from bb::fq. We first convert to uint256_t as field elements are in M...
Definition bigfield.hpp:146
static constexpr uint256_t get_maximum_unreduced_limb_value()
Definition bigfield.hpp:926
static constexpr uint64_t NUM_LAST_LIMB_BITS
Definition bigfield.hpp:317
void set_free_witness_tag()
Set the free witness flag for the bigfield.
Definition bigfield.hpp:714
static constexpr uint512_t get_prohibited_value()
Definition bigfield.hpp:785
bigfield & operator=(const bigfield &other)
void convert_constant_to_fixed_witness(Builder *builder)
Definition bigfield.hpp:661
uint512_t get_maximum_value() const
std::array< uint256_t, NUM_LIMBS > get_binary_basis_limb_maximums()
Get the maximum values of the binary basis limbs.
static uint512_t compute_maximum_quotient_value(const std::vector< uint512_t > &as, const std::vector< uint512_t > &bs, const std::vector< uint512_t > &to_add)
Compute the maximum possible value of quotient of a*b+\sum(to_add)
bigfield sqradd(const std::vector< bigfield > &to_add) const
Square and add operator, computes a * a + ...to_add = c mod p.
static constexpr size_t NUM_LIMBS
Definition bigfield.hpp:72
bigfield operator*=(const bigfield &other)
Definition bigfield.hpp:468
static constexpr uint512_t negative_prime_modulus_mod_binary_basis
Definition bigfield.hpp:342
static bigfield one()
Definition bigfield.hpp:623
static constexpr uint256_t DEFAULT_MAXIMUM_LIMB
Definition bigfield.hpp:325
bigfield add_two(const bigfield &add_a, const bigfield &add_b) const
Create constraints for summing three bigfield elements efficiently.
std::array< uint32_t, NUM_LIMBS > get_binary_basis_limb_witness_indices() const
Get the witness indices of the (normalized) binary basis limbs.
Definition bigfield.hpp:954
bigfield(const unsigned long long value)
Definition bigfield.hpp:136
static constexpr size_t MAXIMUM_SUMMAND_COUNT
Definition bigfield.hpp:333
static bigfield reconstruct_from_public(const std::span< const field_ct, PUBLIC_INPUTS_SIZE > &limbs)
Reconstruct a bigfield from limbs (generally stored in the public inputs)
Definition bigfield.hpp:750
bb::OriginTag get_origin_tag() const
Definition bigfield.hpp:702
bigfield operator-=(const bigfield &other)
Definition bigfield.hpp:463
static bigfield from_witness(Builder *ctx, const bb::field< T > &input)
Definition bigfield.hpp:296
void reduction_check() const
Check if the bigfield element needs to be reduced.
static constexpr bb::fr negative_prime_modulus_mod_native_basis
Definition bigfield.hpp:341
static constexpr uint256_t modulus
Definition bigfield.hpp:314
static bigfield from_witness(Builder *ctx, const OT &input)=delete
static constexpr bb::fr shift_2
Definition bigfield.hpp:339
bigfield(const int value)
Constructs a new bigfield object from an int value. We first need to to construct a field element fro...
Definition bigfield.hpp:126
static bigfield dual_madd(const bigfield &left_a, const bigfield &right_a, const bigfield &left_b, const bigfield &right_b, const std::vector< bigfield > &to_add)
bigfield sqr() const
Square operator, computes a * a = c mod p.
static void perform_reductions_for_mult_madd(std::vector< bigfield > &mul_left, std::vector< bigfield > &mul_right, const std::vector< bigfield > &to_add)
Performs individual reductions on the supplied elements as well as more complex reductions to prevent...
static constexpr bb::fr shift_3
Definition bigfield.hpp:340
bool is_constant() const
Check if the bigfield is constant, i.e. its prime limb is constant.
Definition bigfield.hpp:599
static std::array< uint32_t, 2 > decompose_non_native_field_double_width_limb(Builder *ctx, const uint32_t limb_idx, const size_t num_limb_bits=(2 *NUM_LIMB_BITS))
Decompose a single witness into two limbs, range constrained to NUM_LIMB_BITS (68) and num_limb_bits ...
void reduce_mod_target_modulus() const
static std::pair< uint512_t, uint512_t > compute_quotient_remainder_values(const bigfield &a, const bigfield &b, const std::vector< bigfield > &to_add)
Compute the quotient and remainder values for dividing (a * b + (to_add[0] + ... + to_add[-1])) with ...
void unsafe_assert_less_than(const uint256_t &upper_limit, std::string const &msg="bigfield::unsafe_assert_less_than") const
Assert that the current bigfield is less than the given upper limit.
bigfield operator+(const bigfield &other) const
Adds two bigfield elements. Inputs are reduced to the modulus if necessary. Requires 4 gates if both ...
void assert_equal(const bigfield &other, std::string const &msg="bigfield::assert_equal") const
static constexpr uint64_t LOG2_BINARY_MODULUS
Definition bigfield.hpp:328
static bigfield create_from_u512_as_witness(Builder *ctx, const uint512_t &value, const bool can_overflow=false, const size_t maximum_bitlength=0)
Creates a bigfield element from a uint512_t. Bigfield element is constructed as a witness and not a c...
bigfield pow(const uint32_t exponent) const
Raise the bigfield element to the power of (out-of-circuit) exponent.
static std::pair< bool, size_t > get_quotient_reduction_info(const std::vector< uint512_t > &as_max, const std::vector< uint512_t > &bs_max, const std::vector< bigfield > &to_add, const std::vector< uint1024_t > &remainders_max={ DEFAULT_MAXIMUM_REMAINDER })
Check for 2 conditions (CRT modulus is overflown or the maximum quotient doesn't fit into range proof...
static bigfield unsafe_construct_from_limbs(const field_t< Builder > &a, const field_t< Builder > &b, const field_t< Builder > &c, const field_t< Builder > &d, const bool can_overflow=false)
Construct a bigfield element from binary limbs that are already reduced.
Definition bigfield.hpp:157
static constexpr bigfield unreduced_zero()
Create an unreduced 0 ~ p*k, where p*k is the minimal multiple of modulus that should be reduced.
Definition bigfield.hpp:644
void sanity_check() const
Perform a sanity check on a value that is about to interact with another value.
static void unsafe_evaluate_multiply_add(const bigfield &input_left, const bigfield &input_to_mul, const std::vector< bigfield > &to_add, const bigfield &input_quotient, const std::vector< bigfield > &input_remainders)
Evaluate a multiply add identity with several added elements and several remainders.
field_t< Builder > prime_basis_limb
Represents a bigfield element in the prime basis: (a mod n) where n is the native modulus.
Definition bigfield.hpp:85
static bigfield div_without_denominator_check(const std::vector< bigfield > &numerators, const bigfield &denominator)
std::array< Limb, NUM_LIMBS > binary_basis_limbs
Represents a bigfield element in the binary basis. A bigfield element is represented as a combination...
Definition bigfield.hpp:80
uint32_t set_public() const
Set the witness indices of the binary basis limbs to public.
Definition bigfield.hpp:737
bool_t< Builder > operator==(const bigfield &other) const
Validate whether two bigfield elements are equal to each other.
bigfield operator/=(const bigfield &other)
Definition bigfield.hpp:473
bigfield operator-() const
Negation operator, works by subtracting this from zero.
Definition bigfield.hpp:456
static constexpr bool is_composite
Definition bigfield.hpp:329
bigfield operator+=(const bigfield &other)
Definition bigfield.hpp:458
static std::pair< uint512_t, uint512_t > compute_partial_schoolbook_multiplication(const std::array< uint256_t, NUM_LIMBS > &a_limbs, const std::array< uint256_t, NUM_LIMBS > &b_limbs)
Compute the partial multiplication of two uint256_t arrays using schoolbook multiplication.
static constexpr bb::fr shift_1
Definition bigfield.hpp:338
void unset_free_witness_tag()
Unset the free witness flag for the bigfield.
Definition bigfield.hpp:725
bigfield(const unsigned long value)
Definition bigfield.hpp:131
void self_reduce() const
Reduce the bigfield element modulo the target modulus.
bigfield invert() const
Inverting function with the assumption that the bigfield element we are calling invert on is not zero...
Definition bigfield.hpp:618
bigfield(const uint256_t &value)
Definition bigfield.hpp:117
static bool mul_product_overflows_crt_modulus(const std::vector< uint512_t > &as_max, const std::vector< uint512_t > &bs_max, const std::vector< bigfield > &to_add)
Definition bigfield.hpp:864
void assert_is_not_equal(const bigfield &other, std::string const &msg="bigfield: prime limb diff is zero, but expected non-zero") const
static constexpr std::array< uint256_t, NUM_LIMBS > neg_modulus_mod_binary_basis_limbs_u256
Definition bigfield.hpp:343
static constexpr uint512_t modulus_u512
Definition bigfield.hpp:315
bigfield operator/(const bigfield &other) const
Implements boolean logic in-circuit.
Definition bool.hpp:59
Represents a dynamic array of bytes in-circuit.
bb::fr additive_constant
Definition field.hpp:93
void clear_round_provenance() const
Definition field.hpp:358
void unset_free_witness_tag() const
Unset the free witness flag for the field element's tag.
Definition field.hpp:356
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:444
bool is_constant() const
Definition field.hpp:429
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
Definition field.hpp:351
void set_origin_tag(const OriginTag &new_tag) const
Definition field.hpp:345
AluTraceBuilder builder
Definition alu.test.cpp:124
FF a
FF b
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:245
uintx< uint256_t > uint512_t
Definition uintx.hpp:307
uintx< uint512_t > uint1024_t
Definition uintx.hpp:309
std::conditional_t< IsGoblinBigGroup< C, Fq, Fr, G >, element_goblin::goblin_element< C, goblin_field< C >, Fr, G >, element_default::element< C, Fq, Fr, G > > element
element wraps either element_default::element or element_goblin::goblin_element depending on parametr...
Definition biggroup.hpp:995
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
General class for prime fields see Prime field documentation["field documentation"] for general imple...
static constexpr uint256_t modulus
Represents a single limb of a bigfield element, with its value and maximum value.
Definition bigfield.hpp:44
Limb & operator=(Limb &&other) noexcept=default
Limb(Limb &&other) noexcept=default
Limb(const field_t< Builder > &input, const uint256_t &max=DEFAULT_MAXIMUM_LIMB)
Definition bigfield.hpp:46
Limb & operator=(const Limb &other)=default
field_t< Builder > element
Definition bigfield.hpp:67
friend std::ostream & operator<<(std::ostream &os, const Limb &a)
Definition bigfield.hpp:56
Limb(const Limb &other)=default