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_normalized_witness_index(),
209 result.binary_basis_limbs[1].element.get_normalized_witness_index(),
210 static_cast<size_t>(NUM_LIMB_BITS),
211 static_cast<size_t>(NUM_LIMB_BITS));
212
213 // Range constrain the last two limbs to NUM_LIMB_BITS and NUM_LAST_LIMB_BITS
214 const size_t num_last_limb_bits = (can_overflow) ? NUM_LIMB_BITS : NUM_LAST_LIMB_BITS;
215 ctx->range_constrain_two_limbs(result.binary_basis_limbs[2].element.get_normalized_witness_index(),
216 result.binary_basis_limbs[3].element.get_normalized_witness_index(),
217 static_cast<size_t>(NUM_LIMB_BITS),
218 static_cast<size_t>(num_last_limb_bits));
219
220 return result;
221 };
222
231 const field_t<Builder>& b,
232 const field_t<Builder>& c,
233 const field_t<Builder>& d,
234 const field_t<Builder>& prime_limb,
235 const bool can_overflow = false)
236 {
237 BB_ASSERT_EQ(a.is_constant(), b.is_constant());
238 BB_ASSERT_EQ(b.is_constant(), c.is_constant());
240 BB_ASSERT_EQ(d.is_constant(), prime_limb.is_constant());
241 bigfield result;
242 result.context = a.context;
243 result.binary_basis_limbs[0] = Limb(field_t(a));
244 result.binary_basis_limbs[1] = Limb(field_t(b));
245 result.binary_basis_limbs[2] = Limb(field_t(c));
246 result.binary_basis_limbs[3] =
248 result.prime_basis_limb = prime_limb;
249 return result;
250 };
251
265 bigfield(const byte_array<Builder>& bytes);
266
267 // Copy constructor
268 bigfield(const bigfield& other);
269
270 // Move constructor
271 bigfield(bigfield&& other) noexcept;
272
273 // Destructor
274 ~bigfield() = default;
275
290 const uint512_t& value,
291 const bool can_overflow = false,
292 const size_t maximum_bitlength = 0);
293
294 static bigfield from_witness(Builder* ctx, const bb::field<T>& input)
295 {
296 uint256_t input_u256(input);
297 field_t<Builder> low(witness_t<Builder>(ctx, bb::fr(input_u256.slice(0, NUM_LIMB_BITS * 2))));
299 auto result = bigfield(low, hi);
300 result.set_free_witness_tag();
301 return result;
302 }
303
304 bigfield& operator=(const bigfield& other);
305 bigfield& operator=(bigfield&& other) noexcept;
306
307 // Code assumes modulus is at most 256 bits so good to define it via a uint256_t
308 static constexpr uint256_t modulus = (uint256_t(T::modulus_0, T::modulus_1, T::modulus_2, T::modulus_3));
309 static constexpr uint512_t modulus_u512 = static_cast<uint512_t>(modulus);
310 static constexpr uint64_t NUM_LIMB_BITS = NUM_LIMB_BITS_IN_FIELD_SIMULATION;
311 static constexpr uint64_t NUM_LAST_LIMB_BITS = modulus_u512.get_msb() + 1 - (NUM_LIMB_BITS * 3);
312
313 // The quotient reduction checks currently only support >=250 bit moduli and moduli >256 have never been tested
314 // (Check zkSecurity audit report issue #12 for explanation)
315 static_assert(modulus_u512.get_msb() + 1 >= 250 && modulus_u512.get_msb() + 1 <= 256);
316
322 static constexpr uint64_t LOG2_BINARY_MODULUS = NUM_LIMB_BITS * NUM_LIMBS;
323 static constexpr bool is_composite = true; // false only when fr is native
324
325 // This limits the size of all vectors that are being used to 16 (we don't really need more)
326 static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG = 4;
327 static constexpr size_t MAXIMUM_SUMMAND_COUNT = 1 << MAXIMUM_SUMMAND_COUNT_LOG;
328
333 static constexpr Basis target_basis{ modulus_u512, static_cast<size_t>(modulus_u512.get_msb() + 1) };
334 static constexpr bb::fr shift_1 = bb::fr(uint256_t(1) << NUM_LIMB_BITS);
335 static constexpr bb::fr shift_2 = bb::fr(uint256_t(1) << (NUM_LIMB_BITS * 2));
336 static constexpr bb::fr shift_3 = bb::fr(uint256_t(1) << (NUM_LIMB_BITS * 3));
337 static constexpr bb::fr shift_right_1 = bb::fr(1) / shift_1;
338 static constexpr bb::fr shift_right_2 = bb::fr(1) / shift_2;
353
364 {
366 // Prevents aliases
368 field_t<Builder> lo = binary_basis_limbs[0].element + (binary_basis_limbs[1].element * shift_1);
369 field_t<Builder> hi = binary_basis_limbs[2].element + (binary_basis_limbs[3].element * shift_1);
370 // n.b. this only works if NUM_LIMB_BITS * 2 is divisible by 8
371 //
372 // We are packing two bigfield limbs each into the field elements `lo` and `hi`.
373 // Thus, each of `lo` and `hi` will contain (NUM_LIMB_BITS * 2) bits. We then convert
374 // `lo` and `hi` to `byte_array` each containing ((NUM_LIMB_BITS * 2) / 8) bytes.
375 // Therefore, it is necessary for (NUM_LIMB_BITS * 2) to be divisible by 8 for correctly
376 // converting `lo` and `hi` to `byte_array`s.
377 BB_ASSERT_EQ((NUM_LIMB_BITS * 2 / 8) * 8, NUM_LIMB_BITS * 2);
378 result.write(byte_array<Builder>(hi, 32 - (NUM_LIMB_BITS / 4)));
379 result.write(byte_array<Builder>(lo, (NUM_LIMB_BITS / 4)));
380 return result;
381 }
382
383 // Gets the integer (uint512_t) value of the bigfield element by combining the binary basis limbs.
384 uint512_t get_value() const;
385
386 // Gets the maximum value of the bigfield element by combining the maximum values of the binary basis limbs.
388
405 bigfield add_to_lower_limb(const field_t<Builder>& other, const uint256_t& other_maximum_value) const;
406
421 bigfield operator+(const bigfield& other) const;
422
434 bigfield add_two(const bigfield& add_a, const bigfield& add_b) const;
435
449 bigfield operator-(const bigfield& other) const;
450
464 bigfield operator*(const bigfield& other) const;
465
476 bigfield operator/(const bigfield& other) const;
477
483 bigfield operator-() const { return bigfield(get_context(), uint256_t(0)) - *this; }
484
486 {
487 *this = operator+(other);
488 return *this;
489 }
491 {
492 *this = operator-(other);
493 return *this;
494 }
496 {
497 *this = operator*(other);
498 return *this;
499 }
501 {
502 *this = operator/(other);
503 return *this;
504 }
505
514 bigfield sqr() const;
515
525 bigfield sqradd(const std::vector<bigfield>& to_add) const;
526
538 bigfield pow(const uint32_t exponent) const;
539
548 bigfield madd(const bigfield& to_mul, const std::vector<bigfield>& to_add) const;
549
551 std::vector<bigfield>& mul_right,
552 const std::vector<bigfield>& to_add);
553
554 static bigfield mult_madd(const std::vector<bigfield>& mul_left,
555 const std::vector<bigfield>& mul_right,
556 const std::vector<bigfield>& to_add,
557 bool fix_remainder_to_zero = false);
558
559 static bigfield dual_madd(const bigfield& left_a,
560 const bigfield& right_a,
561 const bigfield& left_b,
562 const bigfield& right_b,
563 const std::vector<bigfield>& to_add);
564
565 // compute -(mul_left * mul_right + ...to_sub) / (divisor)
566 // We can evaluate this relationship with only one set of quotient/remainder range checks
567 static bigfield msub_div(const std::vector<bigfield>& mul_left,
568 const std::vector<bigfield>& mul_right,
569 const bigfield& divisor,
570 const std::vector<bigfield>& to_sub,
571 bool enable_divisor_nz_check = false);
572
573 static bigfield sum(const std::vector<bigfield>& terms);
574 static bigfield internal_div(const std::vector<bigfield>& numerators,
575 const bigfield& denominator,
576 bool check_for_zero);
577
578 static bigfield div_without_denominator_check(const std::vector<bigfield>& numerators, const bigfield& denominator);
580 static bigfield div_check_denominator_nonzero(const std::vector<bigfield>& numerators, const bigfield& denominator);
581
582 bigfield conditional_negate(const bool_t<Builder>& predicate) const;
583
593 bigfield conditional_select(const bigfield& other, const bool_t<Builder>& predicate) const;
594 static bigfield conditional_assign(const bool_t<Builder>& predicate, const bigfield& lhs, const bigfield& rhs)
595 {
596 return rhs.conditional_select(lhs, predicate);
597 }
598
599 bool_t<Builder> operator==(const bigfield& other) const;
600
601 void assert_is_in_field() const;
602 void assert_less_than(const uint256_t& upper_limit) const;
603 void assert_equal(const bigfield& other) const;
604 void assert_is_not_equal(const bigfield& other) const;
605
606 void self_reduce() const;
607
615 bool is_constant() const
616 {
617 bool is_limb_0_constant = binary_basis_limbs[0].element.is_constant();
618 bool is_limb_1_constant = binary_basis_limbs[1].element.is_constant();
619 bool is_limb_2_constant = binary_basis_limbs[2].element.is_constant();
620 bool is_limb_3_constant = binary_basis_limbs[3].element.is_constant();
621 bool is_prime_limb_constant = prime_basis_limb.is_constant();
622 BB_ASSERT_EQ(is_limb_0_constant, is_limb_1_constant);
623 BB_ASSERT_EQ(is_limb_1_constant, is_limb_2_constant);
624 BB_ASSERT_EQ(is_limb_2_constant, is_limb_3_constant);
625 BB_ASSERT_EQ(is_limb_3_constant, is_prime_limb_constant);
626 return is_prime_limb_constant;
627 }
628
634 bigfield invert() const { return (bigfield(1) / bigfield(*this)); }
635
639 static bigfield one()
640 {
641 bigfield result(nullptr, uint256_t(1));
642 return result;
643 }
644
648 static bigfield zero()
649 {
650 bigfield result(nullptr, uint256_t(0));
651 return result;
652 }
653
660 static constexpr bigfield unreduced_zero()
661 {
662 uint512_t multiple_of_modulus = ((get_maximum_unreduced_value() / modulus_u512) + 1) * modulus_u512;
663 auto msb = multiple_of_modulus.get_msb();
664
665 bigfield result(nullptr, uint256_t(0));
666 result.binary_basis_limbs[0] = Limb(bb::fr(multiple_of_modulus.slice(0, NUM_LIMB_BITS).lo));
667 result.binary_basis_limbs[1] = Limb(bb::fr(multiple_of_modulus.slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS).lo));
668 result.binary_basis_limbs[2] = Limb(bb::fr(multiple_of_modulus.slice(2 * NUM_LIMB_BITS, 3 * NUM_LIMB_BITS).lo));
669 result.binary_basis_limbs[3] = Limb(bb::fr(multiple_of_modulus.slice(3 * NUM_LIMB_BITS, msb + 1).lo));
670 result.prime_basis_limb = field_t<Builder>((multiple_of_modulus % uint512_t(field_t<Builder>::modulus)).lo);
671 return result;
672 }
673
678 {
680 for (auto& limb : binary_basis_limbs) {
681 limb.element.convert_constant_to_fixed_witness(context);
682 }
684 }
685
690 {
691 // Origin tags should be updated within
692 for (auto& limb : binary_basis_limbs) {
693 limb.element.fix_witness();
694 }
696
697 // This is now effectively a constant
699 }
700
701 Builder* get_context() const { return context; }
702
703 void set_origin_tag(const bb::OriginTag& tag) const
704 {
705 for (size_t i = 0; i < NUM_LIMBS; i++) {
706 binary_basis_limbs[i].element.set_origin_tag(tag);
707 }
709 }
710
712 {
714 binary_basis_limbs[1].element.tag,
715 binary_basis_limbs[2].element.tag,
716 binary_basis_limbs[3].element.tag,
718 }
719
724 {
725 for (auto& limb : binary_basis_limbs) {
726 limb.element.set_free_witness_tag();
727 }
729 }
730
735 {
736 for (auto& limb : binary_basis_limbs) {
737 limb.element.unset_free_witness_tag();
738 }
740 }
746 uint32_t set_public() const
747 {
748 Builder* ctx = get_context();
749 const uint32_t start_index = static_cast<uint32_t>(ctx->num_public_inputs());
750 for (auto& limb : binary_basis_limbs) {
751 ctx->set_public_input(limb.element.normalize().witness_index);
752 }
753 return start_index;
754 }
755
760 {
761 return construct_from_limbs(limbs[0], limbs[1], limbs[2], limbs[3], /*can_overflow=*/false);
762 }
763
765 {
766 // This = `T * n = 2^272 * |BN(Fr)|` So this equals n*2^t
767 uint1024_t maximum_product = get_maximum_crt_product();
768
769 // In multiplying two bigfield elements a and b, we must check that:
770 //
771 // a * b = q * p + r
772 //
773 // where p is the quotient, r is the remainder, and p is the size of the non-native field.
774 // The CRT requires that we check that the equation:
775 // (a) holds modulo the size of the native field n,
776 // (b) holds modulo the size of the bigger ring 2^t,
777 // (c) both sides of the equation are less than the max product M = 2^t * n.
778 // Thus, the max value of an unreduced bigfield element is √M. In this case, we use
779 // an even stricter bound. Let n = 2^m + l (where 1 < l < 2^m). Thus, we have:
780 //
781 // M = 2^t * n = 2^t * (2^m + l) = 2^(t + m) + (2^t * l)
782 // => M > 2^(t + m)
783 // => √M > 2^((t + m) / 2)
784 //
785 // We set the maximum unreduced value of a bigfield element to be: 2^((t + m) / 2) < √M.
786 //
787 // Note: We use a further safer bound of 2^((t + m - 1) / 2). We use -1 to stay safer,
788 // because it provides additional space to avoid the overflow, but get_msb() by itself should be enough.
789 uint64_t maximum_product_bits = maximum_product.get_msb() - 1;
790 return (uint512_t(1) << (maximum_product_bits >> 1));
791 }
792
793 // If we encounter this maximum value of a bigfield we stop execution
795 {
796 uint1024_t maximum_product = get_maximum_crt_product();
797 uint64_t maximum_product_bits = maximum_product.get_msb() - 1;
798 const size_t arbitrary_secure_margin = 20;
799 return (uint512_t(1) << ((maximum_product_bits >> 1) + arbitrary_secure_margin)) - uint512_t(1);
800 }
801
812 {
814 return maximum_product;
815 }
816
827 static size_t get_quotient_max_bits(const std::vector<uint1024_t>& remainders_max)
828 {
829 // find q_max * p + ...remainders_max < nT
831 for (const auto& r : remainders_max) {
832 base -= r;
833 }
834 base /= modulus_u512;
835 return static_cast<size_t>(base.get_msb() - 1);
836 }
837
848 const uint1024_t& b_max,
849 const std::vector<bigfield>& to_add)
850 {
851 uint1024_t product = a_max * b_max;
852 uint1024_t add_term = 0;
853 for (const auto& add : to_add) {
854 add_term += add.get_maximum_value();
855 }
856 constexpr uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
857
858 // check that the add terms alone cannot overflow the crt modulus. v. unlikely so just forbid circuits that
859 // trigger this case
860 BB_ASSERT_LT(add_term + maximum_default_bigint, get_maximum_crt_product());
861 return ((product + add_term) >= get_maximum_crt_product());
862 }
863
874 const std::vector<uint512_t>& bs_max,
875 const std::vector<bigfield>& to_add)
876 {
878 BB_ASSERT_EQ(as_max.size(), bs_max.size());
879 // Computing individual products
880 uint1024_t product_sum = 0;
881 uint1024_t add_term = 0;
882 for (size_t i = 0; i < as_max.size(); i++) {
883 product_sum += uint1024_t(as_max[i]) * uint1024_t(bs_max[i]);
884 }
885 for (const auto& add : to_add) {
886 add_term += add.get_maximum_value();
887 }
888 static const uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
889
890 // check that the add terms alone cannot overflow the crt modulus. v. unlikely so just forbid circuits that
891 // trigger this case
892 BB_ASSERT_LT(add_term + maximum_default_bigint, get_maximum_crt_product());
893 return ((product_sum + add_term) >= get_maximum_crt_product());
894 }
895
896 // a (currently generous) upper bound on the log of number of fr additions in any of the class operations
897 static constexpr uint64_t MAX_ADDITION_LOG = 10;
898
899 // The rationale of the expression is we should not overflow Fr when applying any bigfield operation (e.g. *) and
900 // starting with this max limb size
901 //
902 // In multiplication of bigfield elements a * b, we encounter sum of limbs multiplications of form:
903 // c0 := a0 * b0
904 // c1 := a1 * b0 + a0 * b1
905 // c2 := a2 * b0 + a1 * b1 + a0 * b2
906 // c3 := a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
907 // output:
908 // lo := c0 + c1 * 2^L,
909 // hi := c2 + c3 * 2^L.
910 // Since hi term contains upto 4 limb-products, we must ensure that the hi term does not overflow the native field
911 // 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
912 // doesn't overflow the native field modulus. Hence:
913 // max(∑ hi) = max(∑ c2 + c3 * 2^L)
914 // = max(∑ c2) + max(∑ c3 * 2^L)
915 // = 2^k * (3 * 2^2Q) + 2^k * 2^L * (4 * 2^2Q)
916 // < 2^k * (2^L + 1) * (4 * 2^2Q)
917 // < n
918 // ==> 2^k * 2^L * 2^(2Q + 2) < n
919 // ==> 2Q + 2 < (log(n) - k - L)
920 // ==> Q < ((log(n) - k - L) - 2) / 2
921 //
922 static constexpr uint64_t MAXIMUM_LIMB_SIZE_THAT_WOULDNT_OVERFLOW =
924
925 // If the logarithm of the maximum value of a limb is more than this, we need to reduce.
926 // We allow an element to be added to itself 10 times, so we allow the limb to grow by 10 bits.
927 // Number 10 is arbitrary, there's no actual usecase for adding 1024 elements together.
928 static constexpr uint64_t MAX_UNREDUCED_LIMB_BITS = NUM_LIMB_BITS + 10;
929
930 // If we reach this size of a limb, we stop execution (as safety measure). This should never reach during addition
931 // as we would reduce the limbs before they reach this size.
932 static constexpr uint64_t PROHIBITED_LIMB_BITS = MAX_UNREDUCED_LIMB_BITS + 5;
933
934 // If we encounter this maximum value of a bigfield we need to reduce it.
936
937 // If we encounter this maximum value of a limb we stop execution
939
941
942 private:
949 {
950 std::array<uint32_t, NUM_LIMBS> limb_witness_indices;
951 for (size_t i = 0; i < NUM_LIMBS; i++) {
952 limb_witness_indices[i] = binary_basis_limbs[i].element.get_normalized_witness_index();
953 }
954 return limb_witness_indices;
955 }
956
966 const bigfield& b,
967 const std::vector<bigfield>& to_add);
977 const std::vector<uint512_t>& bs,
978 const std::vector<uint512_t>& to_add);
979
991 const std::vector<uint512_t>& bs_max,
992 const std::vector<bigfield>& to_add,
993 const std::vector<uint1024_t>& remainders_max = {
995
1015 static void unsafe_evaluate_multiply_add(const bigfield& input_left,
1016 const bigfield& input_to_mul,
1017 const std::vector<bigfield>& to_add,
1018 const bigfield& input_quotient,
1019 const std::vector<bigfield>& input_remainders);
1020
1041 const std::vector<bigfield>& input_right,
1042 const std::vector<bigfield>& to_add,
1043 const bigfield& input_quotient,
1044 const std::vector<bigfield>& input_remainders);
1045
1060 static void unsafe_evaluate_square_add(const bigfield& left,
1061 const std::vector<bigfield>& to_add,
1062 const bigfield& quotient,
1063 const bigfield& remainder);
1064
1085 void reduction_check() const;
1086
1093 void sanity_check() const;
1094
1101 {
1103 for (size_t i = 0; i < NUM_LIMBS; i++) {
1104 limb_maximums[i] = binary_basis_limbs[i].maximum_value;
1105 }
1106 return limb_maximums;
1107 }
1108
1123
1124}; // namespace stdlib
1125
1126template <typename C, typename T> inline std::ostream& operator<<(std::ostream& os, bigfield<T, C> const& v)
1127{
1128 return os << v.get_value();
1129}
1130
1131} // namespace bb::stdlib
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:59
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:129
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:115
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 bigfield zero()
Definition bigfield.hpp:648
static constexpr uint256_t DEFAULT_MAXIMUM_MOST_SIGNIFICANT_LIMB
Definition bigfield.hpp:320
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:827
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:230
static constexpr uint512_t get_maximum_unreduced_value()
Definition bigfield.hpp:764
static constexpr uint256_t get_prohibited_limb_value()
Definition bigfield.hpp:938
static constexpr uint256_t prime_basis_maximum_limb
Definition bigfield.hpp:329
static constexpr uint64_t NUM_LIMB_BITS
Definition bigfield.hpp:310
static constexpr Basis binary_basis
Definition bigfield.hpp:332
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:897
static bigfield conditional_assign(const bool_t< Builder > &predicate, const bigfield &lhs, const bigfield &rhs)
Definition bigfield.hpp:594
static constexpr uint64_t MAX_UNREDUCED_LIMB_BITS
Definition bigfield.hpp:928
static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG
Definition bigfield.hpp:326
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:847
void assert_is_not_equal(const bigfield &other) const
Builder * get_context() const
Definition bigfield.hpp:701
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:811
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:922
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.
byte_array< Builder > to_byte_array() const
Convert the bigfield element to a byte array. Concatenates byte arrays of the high (2L bits) and low ...
Definition bigfield.hpp:363
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:703
uint512_t get_value() const
static bigfield internal_div(const std::vector< bigfield > &numerators, const bigfield &denominator, bool check_for_zero)
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=false)
static constexpr size_t PUBLIC_INPUTS_SIZE
Definition bigfield.hpp:31
static constexpr bb::fr shift_right_2
Definition bigfield.hpp:338
static constexpr uint512_t negative_prime_modulus
Definition bigfield.hpp:340
static constexpr Basis target_basis
Definition bigfield.hpp:333
static constexpr uint64_t PROHIBITED_LIMB_BITS
Definition bigfield.hpp:932
static constexpr Basis prime_basis
Definition bigfield.hpp:331
static const uint1024_t DEFAULT_MAXIMUM_REMAINDER
Definition bigfield.hpp:317
void assert_equal(const bigfield &other) const
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:935
static constexpr bb::fr negative_prime_modulus_mod_binary_basis
Definition bigfield.hpp:339
static constexpr uint64_t NUM_LAST_LIMB_BITS
Definition bigfield.hpp:311
void set_free_witness_tag()
Set the free witness flag for the bigfield.
Definition bigfield.hpp:723
static constexpr uint512_t get_prohibited_value()
Definition bigfield.hpp:794
bigfield & operator=(const bigfield &other)
void convert_constant_to_fixed_witness(Builder *builder)
Definition bigfield.hpp:677
void assert_is_in_field() const
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:495
static bigfield one()
Definition bigfield.hpp:639
static constexpr uint256_t DEFAULT_MAXIMUM_LIMB
Definition bigfield.hpp:319
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:948
bigfield(const unsigned long long value)
Definition bigfield.hpp:136
static constexpr size_t MAXIMUM_SUMMAND_COUNT
Definition bigfield.hpp:327
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:759
bb::OriginTag get_origin_tag() const
Definition bigfield.hpp:711
bigfield operator-=(const bigfield &other)
Definition bigfield.hpp:490
static bigfield from_witness(Builder *ctx, const bb::field< T > &input)
Definition bigfield.hpp:294
void reduction_check() const
Check if the bigfield element needs to be reduced.
static constexpr uint256_t modulus
Definition bigfield.hpp:308
static constexpr bb::fr shift_2
Definition bigfield.hpp:335
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 constexpr bb::fr shift_right_1
Definition bigfield.hpp:337
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:336
bool is_constant() const
Check if the bigfield is constant, i.e. its prime limb is constant.
Definition bigfield.hpp:615
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 ...
static constexpr std::array< uint256_t, NUM_LIMBS > neg_modulus_limbs_u256
Definition bigfield.hpp:341
bigfield operator+(const bigfield &other) const
Adds two bigfield elements. Inputs are reduced to the modulus if necessary. Requires 4 gates if both ...
static constexpr std::array< bb::fr, NUM_LIMBS > neg_modulus_limbs
Definition bigfield.hpp:347
static constexpr uint64_t LOG2_BINARY_MODULUS
Definition bigfield.hpp:322
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:660
void sanity_check() const
Perform a sanity check on a value that is about to interact with another value.
void assert_less_than(const uint256_t &upper_limit) const
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:746
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:500
bigfield operator-() const
Negation operator, works by subtracting this from zero.
Definition bigfield.hpp:483
static constexpr bool is_composite
Definition bigfield.hpp:323
bigfield operator+=(const bigfield &other)
Definition bigfield.hpp:485
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:334
void unset_free_witness_tag()
Unset the free witness flag for the bigfield.
Definition bigfield.hpp:734
bigfield(const unsigned long value)
Definition bigfield.hpp:131
bigfield invert() const
Inverting function with the assumption that the bigfield element we are calling invert on is not zero...
Definition bigfield.hpp:634
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:873
static constexpr uint512_t modulus_u512
Definition bigfield.hpp:309
bigfield operator/(const bigfield &other) const
Implements boolean logic in-circuit.
Definition bool.hpp:59
Represents a dynamic array of bytes in-circuit.
byte_array & write(byte_array const &other)
Appends the contents of another byte_array (other) to the end of this one.
bb::fr additive_constant
Definition field.hpp:88
void unset_free_witness_tag() const
Unset the free witness flag for the field element's tag.
Definition field.hpp:343
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:414
bool is_constant() const
Definition field.hpp:399
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
Definition field.hpp:338
void set_origin_tag(const OriginTag &new_tag) const
Definition field.hpp:332
AluTraceBuilder builder
Definition alu.test.cpp:123
FF a
FF b
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:246
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...
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