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: Complete, auditors: [Suyash], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
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"
12#include "../field/field_utils.hpp"
19
20namespace bb::stdlib {
21
22template <typename Builder, typename T> class bigfield {
23
24 public:
25 using View = bigfield;
27 using TParams = T;
30
31 // Number of bb::fr field elements used to represent a bigfield element in the public inputs
32 static constexpr size_t PUBLIC_INPUTS_SIZE = BIGFIELD_PUBLIC_INPUTS_SIZE;
33
34 struct Basis {
36 size_t num_bits;
37 };
38
45 struct Limb {
46 Limb() = default;
48 : element(input)
49 {
50 if (input.is_constant()) {
53 } else {
54 maximum_value = max;
55 }
56 }
57 friend std::ostream& operator<<(std::ostream& os, const Limb& a)
58 {
59 os << "{ " << a.element << " <= " << a.maximum_value << " }";
60 return os;
61 }
62 Limb(const Limb& other) = default;
63 Limb(Limb&& other) noexcept = default;
64 Limb& operator=(const Limb& other) = default;
65 Limb& operator=(Limb&& other) noexcept = default;
66 ~Limb() = default;
67
70 };
71
72 // Number of limbs used to represent a bigfield element in the binary basis
73 static constexpr size_t NUM_LIMBS = 4;
74
76
82
87
97 bigfield(const field_t<Builder>& low_bits,
98 const field_t<Builder>& high_bits,
99 const bool can_overflow = false,
100 const size_t maximum_bitlength = 0);
101
108 bigfield(Builder* parent_context = nullptr);
109
116 bigfield(Builder* parent_context, const uint256_t& value);
117
118 explicit bigfield(const uint256_t& value)
119 : bigfield(nullptr, uint256_t(value))
120 {}
121
127 bigfield(const int value)
128 : bigfield(nullptr, uint256_t(native(value)))
129 {}
130
131 // NOLINTNEXTLINE(google-runtime-int) intended behavior
132 bigfield(const unsigned long value)
133 : bigfield(nullptr, value)
134 {}
135
136 // NOLINTNEXTLINE(google-runtime-int) intended behavior
137 bigfield(const unsigned long long value)
138 : bigfield(nullptr, value)
139 {}
140
148 : bigfield(nullptr, uint256_t(value))
149 {}
150
159 const field_t<Builder>& b,
160 const field_t<Builder>& c,
161 const field_t<Builder>& d,
162 const bool can_overflow = false)
163 {
164 BB_ASSERT_EQ(a.is_constant(), b.is_constant());
165 BB_ASSERT_EQ(b.is_constant(), c.is_constant());
167 bigfield result;
168 result.context = a.context;
169 result.binary_basis_limbs[0] = Limb(field_t(a));
170 result.binary_basis_limbs[1] = Limb(field_t(b));
171 result.binary_basis_limbs[2] = Limb(field_t(c));
172 result.binary_basis_limbs[3] =
174 result.prime_basis_limb = (result.binary_basis_limbs[3].element * shift_3)
175 .add_two(result.binary_basis_limbs[2].element * shift_2,
176 result.binary_basis_limbs[1].element * shift_1);
177 result.prime_basis_limb += (result.binary_basis_limbs[0].element);
178 return result;
179 };
180
187 const field_t<Builder>& b,
188 const field_t<Builder>& c,
189 const field_t<Builder>& d,
190 const bool can_overflow = false)
191 {
192 BB_ASSERT_EQ(a.is_constant(), b.is_constant());
193 BB_ASSERT_EQ(b.is_constant(), c.is_constant());
195 bigfield result;
196 auto ctx = a.context;
197 result.context = a.context;
198 result.binary_basis_limbs[0] = Limb(field_t(a));
199 result.binary_basis_limbs[1] = Limb(field_t(b));
200 result.binary_basis_limbs[2] = Limb(field_t(c));
201 result.binary_basis_limbs[3] =
203 result.prime_basis_limb = (result.binary_basis_limbs[3].element * shift_3)
204 .add_two(result.binary_basis_limbs[2].element * shift_2,
205 result.binary_basis_limbs[1].element * shift_1);
206 result.prime_basis_limb += (result.binary_basis_limbs[0].element);
207
208 // Range contrain the first two limbs each to NUM_LIMB_BITS
209 ctx->range_constrain_two_limbs(result.binary_basis_limbs[0].element.get_witness_index(),
210 result.binary_basis_limbs[1].element.get_witness_index(),
211 static_cast<size_t>(NUM_LIMB_BITS),
212 static_cast<size_t>(NUM_LIMB_BITS),
213 "bigfield::construct_from_limbs: limb 0 or 1 too large");
214
215 // Range constrain the last two limbs to NUM_LIMB_BITS and NUM_LAST_LIMB_BITS
216 const size_t num_last_limb_bits = (can_overflow) ? NUM_LIMB_BITS : NUM_LAST_LIMB_BITS;
217 ctx->range_constrain_two_limbs(result.binary_basis_limbs[2].element.get_witness_index(),
218 result.binary_basis_limbs[3].element.get_witness_index(),
219 static_cast<size_t>(NUM_LIMB_BITS),
220 static_cast<size_t>(num_last_limb_bits),
221 "bigfield::construct_from_limbs: limb 2 or 3 too large");
222
223 return result;
224 };
225
234 const field_t<Builder>& b,
235 const field_t<Builder>& c,
236 const field_t<Builder>& d,
237 const field_t<Builder>& prime_limb,
238 const bool can_overflow = false)
239 {
240 BB_ASSERT_EQ(a.is_constant(), b.is_constant());
241 BB_ASSERT_EQ(b.is_constant(), c.is_constant());
243 BB_ASSERT_EQ(d.is_constant(), prime_limb.is_constant());
244 bigfield result;
245 result.context = a.context;
246 result.binary_basis_limbs[0] = Limb(field_t(a));
247 result.binary_basis_limbs[1] = Limb(field_t(b));
248 result.binary_basis_limbs[2] = Limb(field_t(c));
249 result.binary_basis_limbs[3] =
251 result.prime_basis_limb = prime_limb;
252 return result;
253 };
254
268 bigfield(const byte_array<Builder>& bytes);
269
270 // Copy constructor
271 bigfield(const bigfield& other);
272
273 // Move constructor
274 bigfield(bigfield&& other) noexcept;
275
276 // Destructor
277 ~bigfield() = default;
278
293 const uint512_t& value,
294 const bool can_overflow = false,
295 const size_t maximum_bitlength = 0);
296
297 static bigfield from_witness(Builder* ctx, const bb::field<T>& input)
298 {
299 uint256_t input_u256(input);
300 field_t<Builder> low(witness_t<Builder>(ctx, bb::fr(input_u256.slice(0, NUM_LIMB_BITS * 2))));
302 auto result = bigfield(low, hi);
303 result.set_free_witness_tag();
304 return result;
305 }
306
307 // Disallow from_witness for non-bb::fr types to prevent implicit conversions (specifically, using indices rather
308 // than values)
309 template <typename OT> static bigfield from_witness(Builder* ctx, const OT& input) = delete;
310
311 bigfield& operator=(const bigfield& other);
312 bigfield& operator=(bigfield&& other) noexcept;
313
314 // Code assumes modulus is at most 256 bits so good to define it via a uint256_t
315 static constexpr uint256_t modulus = (uint256_t(T::modulus_0, T::modulus_1, T::modulus_2, T::modulus_3));
316 static constexpr uint512_t modulus_u512 = static_cast<uint512_t>(modulus);
317 static constexpr uint64_t NUM_LIMB_BITS = NUM_LIMB_BITS_IN_FIELD_SIMULATION;
318 static constexpr uint64_t NUM_LAST_LIMB_BITS = modulus_u512.get_msb() + 1 - (NUM_LIMB_BITS * 3);
319
320 // The quotient reduction checks currently only support >=250 bit moduli and moduli >256 have never been tested
321 // (Check zkSecurity audit report issue #12 for explanation)
322 static_assert(modulus_u512.get_msb() + 1 >= 250 && modulus_u512.get_msb() + 1 <= 256);
323
329 static constexpr uint64_t LOG2_BINARY_MODULUS = NUM_LIMB_BITS * NUM_LIMBS;
330 static constexpr bool is_composite = true; // false only when fr is native
331
332 // This limits the size of all vectors that are being used to 16 (we don't really need more)
333 static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG = 4;
334 static constexpr size_t MAXIMUM_SUMMAND_COUNT = 1 << MAXIMUM_SUMMAND_COUNT_LOG;
335
338 static constexpr Basis target_basis{ modulus_u512, static_cast<size_t>(modulus_u512.get_msb() + 1) };
339 static constexpr bb::fr shift_1 = bb::fr(uint256_t(1) << NUM_LIMB_BITS);
340 static constexpr bb::fr shift_2 = bb::fr(uint256_t(1) << (NUM_LIMB_BITS * 2));
341 static constexpr bb::fr shift_3 = bb::fr(uint256_t(1) << (NUM_LIMB_BITS * 3));
356
357 // Gets the integer (uint512_t) value of the bigfield element by combining the binary basis limbs.
358 uint512_t get_value() const;
359
360 // Gets the maximum value of the bigfield element by combining the maximum values of the binary basis limbs.
362
379 bigfield add_to_lower_limb(const field_t<Builder>& other, const uint256_t& other_maximum_value) const;
380
395 bigfield operator+(const bigfield& other) const;
396
408 bigfield add_two(const bigfield& add_a, const bigfield& add_b) const;
409
423 bigfield operator-(const bigfield& other) const;
424
438 bigfield operator*(const bigfield& other) const;
439
450 bigfield operator/(const bigfield& other) const;
451
457 bigfield operator-() const { return bigfield(get_context(), uint256_t(0)) - *this; }
458
460 {
461 *this = operator+(other);
462 return *this;
463 }
465 {
466 *this = operator-(other);
467 return *this;
468 }
470 {
471 *this = operator*(other);
472 return *this;
473 }
475 {
476 *this = operator/(other);
477 return *this;
478 }
479
488 bigfield sqr() const;
489
499 bigfield sqradd(const std::vector<bigfield>& to_add) const;
500
512 bigfield pow(const uint32_t exponent) const;
513
522 bigfield madd(const bigfield& to_mul, const std::vector<bigfield>& to_add) const;
523
525 std::vector<bigfield>& mul_right,
526 const std::vector<bigfield>& to_add);
527
528 static bigfield mult_madd(const std::vector<bigfield>& mul_left,
529 const std::vector<bigfield>& mul_right,
530 const std::vector<bigfield>& to_add,
531 bool fix_remainder_to_zero = false);
532
533 static bigfield dual_madd(const bigfield& left_a,
534 const bigfield& right_a,
535 const bigfield& left_b,
536 const bigfield& right_b,
537 const std::vector<bigfield>& to_add);
538
539 // compute -(mul_left * mul_right + ...to_sub) / (divisor)
540 // We can evaluate this relationship with only one set of quotient/remainder range checks
541 static bigfield msub_div(const std::vector<bigfield>& mul_left,
542 const std::vector<bigfield>& mul_right,
543 const bigfield& divisor,
544 const std::vector<bigfield>& to_sub,
545 bool enable_divisor_nz_check = true);
546
547 static bigfield sum(const std::vector<bigfield>& terms);
548 static bigfield internal_div(const std::vector<bigfield>& numerators,
549 const bigfield& denominator,
550 bool check_for_zero);
551
552 static bigfield div_without_denominator_check(const std::vector<bigfield>& numerators, const bigfield& denominator);
554 static bigfield div_check_denominator_nonzero(const std::vector<bigfield>& numerators, const bigfield& denominator);
555
556 bigfield conditional_negate(const bool_t<Builder>& predicate) const;
557
567 bigfield conditional_select(const bigfield& other, const bool_t<Builder>& predicate) const;
568 static bigfield conditional_assign(const bool_t<Builder>& predicate, const bigfield& lhs, const bigfield& rhs)
569 {
570 return rhs.conditional_select(lhs, predicate);
571 }
572
573 bool_t<Builder> operator==(const bigfield& other) const;
574
575 void assert_zero_if(const bool_t<Builder>& predicate,
576 std::string const& msg = "bigfield::assert_zero_if failed") const;
577 void assert_is_in_field(std::string const& msg = "bigfield::assert_is_in_field") const;
578 void assert_less_than(const uint256_t& upper_limit, std::string const& msg = "bigfield::assert_less_than") const;
579 void reduce_mod_target_modulus() const;
580 void assert_equal(const bigfield& other, std::string const& msg = "bigfield::assert_equal") const;
581 void assert_is_not_equal(const bigfield& other,
582 std::string const& msg = "bigfield: prime limb diff is zero, but expected non-zero") const;
583
593 void self_reduce() const;
594
602 bool is_constant() const
603 {
604 bool is_limb_0_constant = binary_basis_limbs[0].element.is_constant();
605 bool is_limb_1_constant = binary_basis_limbs[1].element.is_constant();
606 bool is_limb_2_constant = binary_basis_limbs[2].element.is_constant();
607 bool is_limb_3_constant = binary_basis_limbs[3].element.is_constant();
608 bool is_prime_limb_constant = prime_basis_limb.is_constant();
609 BB_ASSERT_EQ(is_limb_0_constant, is_limb_1_constant);
610 BB_ASSERT_EQ(is_limb_1_constant, is_limb_2_constant);
611 BB_ASSERT_EQ(is_limb_2_constant, is_limb_3_constant);
612 BB_ASSERT_EQ(is_limb_3_constant, is_prime_limb_constant);
613 return is_prime_limb_constant;
614 }
615
621 bigfield invert() const { return (bigfield(1) / bigfield(*this)); }
622
626 static bigfield one()
627 {
628 bigfield result(nullptr, uint256_t(1));
629 return result;
630 }
631
635 static bigfield zero()
636 {
637 bigfield result(nullptr, uint256_t(0));
638 return result;
639 }
640
647 static constexpr bigfield unreduced_zero()
648 {
649 uint512_t multiple_of_modulus = ((get_maximum_unreduced_value() / modulus_u512) + 1) * modulus_u512;
650 auto msb = multiple_of_modulus.get_msb();
651
652 bigfield result(nullptr, uint256_t(0));
653 result.binary_basis_limbs[0] = Limb(bb::fr(multiple_of_modulus.slice(0, NUM_LIMB_BITS).lo));
654 result.binary_basis_limbs[1] = Limb(bb::fr(multiple_of_modulus.slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS).lo));
655 result.binary_basis_limbs[2] = Limb(bb::fr(multiple_of_modulus.slice(2 * NUM_LIMB_BITS, 3 * NUM_LIMB_BITS).lo));
656 result.binary_basis_limbs[3] = Limb(bb::fr(multiple_of_modulus.slice(3 * NUM_LIMB_BITS, msb + 1).lo));
657 result.prime_basis_limb = field_t<Builder>((multiple_of_modulus % uint512_t(field_t<Builder>::modulus)).lo);
658 return result;
659 }
660
665 {
667 for (auto& limb : binary_basis_limbs) {
668 limb.element.convert_constant_to_fixed_witness(context);
669 }
671 }
672
677 {
678 // Origin tags should be updated within
679 for (auto& limb : binary_basis_limbs) {
680 limb.element.fix_witness();
681 }
683
684 // This is now effectively a constant
686 }
687
688 Builder* get_context() const { return context; }
689
691 {
692 for (size_t i = 0; i < NUM_LIMBS; i++) {
693 binary_basis_limbs[i].element.set_origin_tag(tag);
694 }
696 }
698 {
699 for (size_t i = 0; i < NUM_LIMBS; i++) {
700 binary_basis_limbs[i].element.clear_round_provenance();
701 }
703 }
704
706 {
708 binary_basis_limbs[1].element.tag,
709 binary_basis_limbs[2].element.tag,
710 binary_basis_limbs[3].element.tag,
712 }
713
718 {
719 for (auto& limb : binary_basis_limbs) {
720 limb.element.set_free_witness_tag();
721 }
723 }
724
729 {
730 for (auto& limb : binary_basis_limbs) {
731 limb.element.unset_free_witness_tag();
732 }
734 }
742 uint32_t set_public() const
743 {
744 // Reduce bigfield to canonical form before combining into 2-limb format.
745 self_reduce();
746
747 Builder* ctx = get_context();
748 const uint32_t start_index = static_cast<uint32_t>(ctx->num_public_inputs());
749
750 // Combine limbs into 2-limb Codec format
751 constexpr uint256_t shift = uint256_t(1) << NUM_LIMB_BITS;
752 field_t<Builder> lo = binary_basis_limbs[0].element + binary_basis_limbs[1].element * shift;
753 field_t<Builder> hi = binary_basis_limbs[2].element + binary_basis_limbs[3].element * shift;
754
755 // Mark as used witnesses (these are intentionally in one gate for public input encoding)
758
759 ctx->set_public_input(lo.get_witness_index());
760 ctx->set_public_input(hi.get_witness_index());
761
762 return start_index;
763 }
764
766 {
767 // This = `T * n = 2^272 * |BN(Fr)|` So this equals n*2^t
768 uint1024_t maximum_product = get_maximum_crt_product();
769
770 // In multiplying two bigfield elements a and b, we must check that:
771 //
772 // a * b = q * p + r
773 //
774 // where q is the quotient, r is the remainder, and p is the size of the non-native field.
775 // The CRT requires that we check that the equation:
776 // (a) holds modulo the size of the native field n,
777 // (b) holds modulo the size of the bigger ring 2^t,
778 // (c) both sides of the equation are less than the max product M = 2^t * n.
779 // Thus, the max value of an unreduced bigfield element is √M. In this case, we use
780 // an even stricter bound. Let n = 2^m + l (where 1 < l < 2^m). Thus, we have:
781 //
782 // M = 2^t * n = 2^t * (2^m + l) = 2^(t + m) + (2^t * l)
783 // => M > 2^(t + m)
784 // => √M > 2^((t + m) / 2)
785 //
786 // We set the maximum unreduced value of a bigfield element to be: 2^((t + m) / 2) < √M.
787 //
788 // Note: We use a further safer bound of 2^((t + m - 1) / 2). We use -1 to stay safer,
789 // because it provides additional space to avoid the overflow, but get_msb() by itself should be enough.
790 uint64_t maximum_product_bits = maximum_product.get_msb() - 1;
791 return (uint512_t(1) << (maximum_product_bits >> 1)) - uint512_t(1);
792 }
793
794 // If we encounter this maximum value of a bigfield we stop execution
796 {
797 uint1024_t maximum_product = get_maximum_crt_product();
798 uint64_t maximum_product_bits = maximum_product.get_msb() - 1;
799 const size_t arbitrary_secure_margin = 20;
800 return (uint512_t(1) << ((maximum_product_bits >> 1) + arbitrary_secure_margin)) - uint512_t(1);
801 }
802
813 {
815 return maximum_product;
816 }
817
828 static size_t get_quotient_max_bits(const std::vector<uint1024_t>& remainders_max)
829 {
830 // find q_max * p + ...remainders_max < nT
832 for (const auto& r : remainders_max) {
833 base -= r;
834 }
835 base /= modulus_u512;
836 return static_cast<size_t>(base.get_msb() - 1);
837 }
838
849 const uint1024_t& b_max,
850 const std::vector<bigfield>& to_add)
851 {
852 uint1024_t product = a_max * b_max;
853 uint1024_t add_term = 0;
854 for (const auto& add : to_add) {
855 add_term += add.get_maximum_value();
856 }
857 constexpr uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
858
859 // check that the add terms alone cannot overflow the crt modulus. v. unlikely so just forbid circuits that
860 // trigger this case
861 BB_ASSERT_LT(add_term + maximum_default_bigint, get_maximum_crt_product());
862 return ((product + add_term) >= get_maximum_crt_product());
863 }
864
875 const std::vector<uint512_t>& bs_max,
876 const std::vector<bigfield>& to_add)
877 {
879 BB_ASSERT_EQ(as_max.size(), bs_max.size());
880 // Computing individual products
881 uint1024_t product_sum = 0;
882 uint1024_t add_term = 0;
883 for (size_t i = 0; i < as_max.size(); i++) {
884 product_sum += uint1024_t(as_max[i]) * uint1024_t(bs_max[i]);
885 }
886 for (const auto& add : to_add) {
887 add_term += add.get_maximum_value();
888 }
889 static const uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
890
891 // check that the add terms alone cannot overflow the crt modulus. v. unlikely so just forbid circuits that
892 // trigger this case
893 BB_ASSERT_LT(add_term + maximum_default_bigint, get_maximum_crt_product());
894 return ((product_sum + add_term) >= get_maximum_crt_product());
895 }
896
897 // a (currently generous) upper bound on the log of number of fr additions in any of the class operations
898 static constexpr uint64_t MAX_ADDITION_LOG = 10;
899
900 // The rationale of the expression is we should not overflow Fr when applying any bigfield operation (e.g. *) and
901 // starting with this max limb size
902 //
903 // In multiplication of bigfield elements a * b, we encounter sum of limbs multiplications of form:
904 // c0 := a0 * b0
905 // c1 := a1 * b0 + a0 * b1
906 // c2 := a2 * b0 + a1 * b1 + a0 * b2
907 // c3 := a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
908 // output:
909 // lo := c0 + c1 * 2^L,
910 // hi := c2 + c3 * 2^L.
911 // Since hi term contains upto 4 limb-products, we must ensure that the hi term does not overflow the native field
912 // 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
913 // doesn't overflow the native field modulus. Hence:
914 // max(∑ hi) = max(∑ c2 + c3 * 2^L)
915 // = max(∑ c2) + max(∑ c3 * 2^L)
916 // = 2^k * (3 * 2^2Q) + 2^k * 2^L * (4 * 2^2Q)
917 // < 2^k * (2^L + 1) * (4 * 2^2Q)
918 // < n
919 // ==> 2^k * 2^L * 2^(2Q + 3) < n
920 // ==> 2Q + 3 < (log(n) - k - L)
921 // ==> Q < ((log(n) - k - L) - 3) / 2
922 //
923 static constexpr uint64_t MAXIMUM_LIMB_SIZE_THAT_WOULDNT_OVERFLOW =
925
926 // If the logarithm of the maximum value of a limb is more than this, we need to reduce.
927 // We allow an element to be added to itself 10 times, so we allow the limb to grow by 10 bits.
928 // Number 10 is arbitrary, there's no actual usecase for adding 1024 elements together.
930
931 // If we reach this size of a limb, we stop execution (as safety measure). This should never reach during addition
932 // as we would reduce the limbs before they reach this size.
933 static constexpr uint64_t PROHIBITED_LIMB_BITS = MAX_UNREDUCED_LIMB_BITS + 5;
934
935 // If we encounter this maximum value of a bigfield we need to reduce it.
937 {
938 return ((uint256_t(1) << MAX_UNREDUCED_LIMB_BITS) - uint256_t(1));
939 }
940
941 // If we encounter this maximum value of a limb we stop execution
943
945
946 // For testing purposes only
948
949 private:
956 void unsafe_assert_less_than(const uint256_t& upper_limit,
957 std::string const& msg = "bigfield::unsafe_assert_less_than") const;
958
965 {
966 std::array<uint32_t, NUM_LIMBS> limb_witness_indices;
967 for (size_t i = 0; i < NUM_LIMBS; i++) {
968 limb_witness_indices[i] = binary_basis_limbs[i].element.get_witness_index();
969 }
970 return limb_witness_indices;
971 }
972
984 static std::array<uint32_t, 2> decompose_non_native_field_double_width_limb(
985 Builder* ctx, const uint32_t limb_idx, const size_t num_limb_bits = (2 * NUM_LIMB_BITS));
986
996 const bigfield& b,
997 const std::vector<bigfield>& to_add);
1007 const std::vector<uint512_t>& bs,
1008 const std::vector<uint512_t>& to_add);
1009
1021 const std::vector<uint512_t>& bs_max,
1022 const std::vector<bigfield>& to_add,
1023 const std::vector<uint1024_t>& remainders_max = {
1025
1045 static void unsafe_evaluate_multiply_add(const bigfield& input_left,
1046 const bigfield& input_to_mul,
1047 const std::vector<bigfield>& to_add,
1048 const bigfield& input_quotient,
1049 const std::vector<bigfield>& input_remainders);
1050
1071 const std::vector<bigfield>& input_right,
1072 const std::vector<bigfield>& to_add,
1073 const bigfield& input_quotient,
1074 const std::vector<bigfield>& input_remainders);
1075
1090 static void unsafe_evaluate_square_add(const bigfield& left,
1091 const std::vector<bigfield>& to_add,
1092 const bigfield& quotient,
1093 const bigfield& remainder);
1094
1115 void reduction_check() const;
1116
1123 void sanity_check() const;
1124
1131 {
1133 for (size_t i = 0; i < NUM_LIMBS; i++) {
1134 limb_maximums[i] = binary_basis_limbs[i].maximum_value;
1135 }
1136 return limb_maximums;
1137 }
1138
1153
1154}; // namespace stdlib
1155
1156// NOTE: For testing private functions in bigfield
1158 public:
1159 template <typename bigfield>
1160 static void unsafe_assert_less_than(const bigfield& input, const uint256_t& upper_limit)
1161 {
1162 input.unsafe_assert_less_than(upper_limit);
1163 }
1164
1165 template <typename bigfield>
1166 static void unsafe_evaluate_multiply_add(const bigfield& input_left,
1167 const bigfield& input_to_mul,
1168 const std::vector<bigfield>& to_add,
1169 const bigfield& input_quotient,
1170 const std::vector<bigfield>& input_remainders)
1171 {
1172 bigfield::unsafe_evaluate_multiply_add(input_left, input_to_mul, to_add, input_quotient, input_remainders);
1173 }
1174
1175 template <typename bigfield>
1177 const std::vector<bigfield>& input_right,
1178 const std::vector<bigfield>& to_add,
1179 const bigfield& input_quotient,
1180 const std::vector<bigfield>& input_remainders)
1181 {
1183 input_left, input_right, to_add, input_quotient, input_remainders);
1184 }
1185};
1186
1187template <typename C, typename T> inline std::ostream& operator<<(std::ostream& os, bigfield<T, C> const& v)
1188{
1189 return os << v.get_value();
1190}
1191
1192} // namespace bb::stdlib
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:158
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:143
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:81
constexpr uint64_t get_msb() const
Definition uintx.hpp:68
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:635
static constexpr uint256_t DEFAULT_MAXIMUM_MOST_SIGNIFICANT_LIMB
Definition bigfield.hpp:327
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:828
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:233
static constexpr uint512_t get_maximum_unreduced_value()
Definition bigfield.hpp:765
static constexpr uint256_t get_prohibited_limb_value()
Definition bigfield.hpp:942
static constexpr uint64_t NUM_LIMB_BITS
Definition bigfield.hpp:317
static constexpr Basis binary_basis
Definition bigfield.hpp:337
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:898
static bigfield conditional_assign(const bool_t< Builder > &predicate, const bigfield &lhs, const bigfield &rhs)
Definition bigfield.hpp:568
static constexpr uint64_t MAX_UNREDUCED_LIMB_BITS
Definition bigfield.hpp:929
static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG
Definition bigfield.hpp:333
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:848
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:697
Builder * get_context() const
Definition bigfield.hpp:688
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:812
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:923
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:186
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:690
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:350
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:32
static constexpr Basis target_basis
Definition bigfield.hpp:338
static constexpr uint64_t PROHIBITED_LIMB_BITS
Definition bigfield.hpp:933
static constexpr Basis prime_basis
Definition bigfield.hpp:336
static const uint1024_t DEFAULT_MAXIMUM_REMAINDER
Definition bigfield.hpp:324
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:147
static constexpr uint256_t get_maximum_unreduced_limb_value()
Definition bigfield.hpp:936
static constexpr uint64_t NUM_LAST_LIMB_BITS
Definition bigfield.hpp:318
void set_free_witness_tag()
Set the free witness flag for the bigfield.
Definition bigfield.hpp:717
static constexpr uint512_t get_prohibited_value()
Definition bigfield.hpp:795
bigfield & operator=(const bigfield &other)
void convert_constant_to_fixed_witness(Builder *builder)
Definition bigfield.hpp:664
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:73
bigfield operator*=(const bigfield &other)
Definition bigfield.hpp:469
static constexpr uint512_t negative_prime_modulus_mod_binary_basis
Definition bigfield.hpp:343
static bigfield one()
Definition bigfield.hpp:626
static constexpr uint256_t DEFAULT_MAXIMUM_LIMB
Definition bigfield.hpp:326
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:964
bigfield(const unsigned long long value)
Definition bigfield.hpp:137
static constexpr size_t MAXIMUM_SUMMAND_COUNT
Definition bigfield.hpp:334
bb::OriginTag get_origin_tag() const
Definition bigfield.hpp:705
bigfield operator-=(const bigfield &other)
Definition bigfield.hpp:464
static bigfield from_witness(Builder *ctx, const bb::field< T > &input)
Definition bigfield.hpp:297
void reduction_check() const
Check if the bigfield element needs to be reduced.
void assert_zero_if(const bool_t< Builder > &predicate, std::string const &msg="bigfield::assert_zero_if failed") const
static constexpr bb::fr negative_prime_modulus_mod_native_basis
Definition bigfield.hpp:342
static constexpr uint256_t modulus
Definition bigfield.hpp:315
static bigfield from_witness(Builder *ctx, const OT &input)=delete
static constexpr bb::fr shift_2
Definition bigfield.hpp:340
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:127
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:341
bool is_constant() const
Check if the bigfield is constant, i.e. its prime limb is constant.
Definition bigfield.hpp:602
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:329
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:158
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:647
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:86
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:81
uint32_t set_public() const
Set the witness indices for the limbs of the bigfield to public.
Definition bigfield.hpp:742
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:474
bigfield operator-() const
Negation operator, works by subtracting this from zero.
Definition bigfield.hpp:457
static constexpr bool is_composite
Definition bigfield.hpp:330
bigfield operator+=(const bigfield &other)
Definition bigfield.hpp:459
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:339
void unset_free_witness_tag()
Unset the free witness flag for the bigfield.
Definition bigfield.hpp:728
bigfield(const unsigned long value)
Definition bigfield.hpp:132
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:621
bigfield(const uint256_t &value)
Definition bigfield.hpp:118
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:874
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:344
static constexpr uint512_t modulus_u512
Definition bigfield.hpp:316
bigfield operator/(const bigfield &other) const
Implements boolean logic in-circuit.
Definition bool.hpp:60
Represents a dynamic array of bytes in-circuit.
bb::fr additive_constant
Definition field.hpp:94
void clear_round_provenance() const
Definition field.hpp:370
void unset_free_witness_tag() const
Unset the free witness flag for the field element's tag.
Definition field.hpp:368
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:456
bool is_constant() const
Definition field.hpp:441
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
Definition field.hpp:363
void set_origin_tag(const OriginTag &new_tag) const
Definition field.hpp:357
uint32_t get_witness_index() const
Get the witness index of the current field element.
Definition field.hpp:518
AluTraceBuilder builder
Definition alu.test.cpp:124
FF a
FF b
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:258
uintx< uint256_t > uint512_t
Definition uintx.hpp:306
uintx< uint512_t > uint1024_t
Definition uintx.hpp:308
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...
void mark_witness_as_used(const field_t< Builder > &field)
Mark a field_t witness as used (for UltraBuilder only).
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:45
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:47
Limb & operator=(const Limb &other)=default
field_t< Builder > element
Definition bigfield.hpp:68
friend std::ostream & operator<<(std::ostream &os, const Limb &a)
Definition bigfield.hpp:57
Limb(const Limb &other)=default