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 "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_normalized_witness_index(),
217 result.binary_basis_limbs[3].element.get_normalized_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 bigfield& operator=(const bigfield& other);
307 bigfield& operator=(bigfield&& other) noexcept;
308
309 // Code assumes modulus is at most 256 bits so good to define it via a uint256_t
310 static constexpr uint256_t modulus = (uint256_t(T::modulus_0, T::modulus_1, T::modulus_2, T::modulus_3));
311 static constexpr uint512_t modulus_u512 = static_cast<uint512_t>(modulus);
312 static constexpr uint64_t NUM_LIMB_BITS = NUM_LIMB_BITS_IN_FIELD_SIMULATION;
313 static constexpr uint64_t NUM_LAST_LIMB_BITS = modulus_u512.get_msb() + 1 - (NUM_LIMB_BITS * 3);
314
315 // The quotient reduction checks currently only support >=250 bit moduli and moduli >256 have never been tested
316 // (Check zkSecurity audit report issue #12 for explanation)
317 static_assert(modulus_u512.get_msb() + 1 >= 250 && modulus_u512.get_msb() + 1 <= 256);
318
324 static constexpr uint64_t LOG2_BINARY_MODULUS = NUM_LIMB_BITS * NUM_LIMBS;
325 static constexpr bool is_composite = true; // false only when fr is native
326
327 // This limits the size of all vectors that are being used to 16 (we don't really need more)
328 static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG = 4;
329 static constexpr size_t MAXIMUM_SUMMAND_COUNT = 1 << MAXIMUM_SUMMAND_COUNT_LOG;
330
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));
351
362 {
364 // Prevents aliases
366 field_t<Builder> lo = binary_basis_limbs[0].element + (binary_basis_limbs[1].element * shift_1);
367 field_t<Builder> hi = binary_basis_limbs[2].element + (binary_basis_limbs[3].element * shift_1);
368 // n.b. this only works if NUM_LIMB_BITS * 2 is divisible by 8
369 //
370 // We are packing two bigfield limbs each into the field elements `lo` and `hi`.
371 // Thus, each of `lo` and `hi` will contain (NUM_LIMB_BITS * 2) bits. We then convert
372 // `lo` and `hi` to `byte_array` each containing ((NUM_LIMB_BITS * 2) / 8) bytes.
373 // Therefore, it is necessary for (NUM_LIMB_BITS * 2) to be divisible by 8 for correctly
374 // converting `lo` and `hi` to `byte_array`s.
375 BB_ASSERT_EQ((NUM_LIMB_BITS * 2 / 8) * 8, NUM_LIMB_BITS * 2);
376 result.write(byte_array<Builder>(hi, 32 - (NUM_LIMB_BITS / 4)));
377 result.write(byte_array<Builder>(lo, (NUM_LIMB_BITS / 4)));
378 return result;
379 }
380
381 // Gets the integer (uint512_t) value of the bigfield element by combining the binary basis limbs.
382 uint512_t get_value() const;
383
384 // Gets the maximum value of the bigfield element by combining the maximum values of the binary basis limbs.
386
403 bigfield add_to_lower_limb(const field_t<Builder>& other, const uint256_t& other_maximum_value) const;
404
419 bigfield operator+(const bigfield& other) const;
420
432 bigfield add_two(const bigfield& add_a, const bigfield& add_b) const;
433
447 bigfield operator-(const bigfield& other) const;
448
462 bigfield operator*(const bigfield& other) const;
463
474 bigfield operator/(const bigfield& other) const;
475
481 bigfield operator-() const { return bigfield(get_context(), uint256_t(0)) - *this; }
482
484 {
485 *this = operator+(other);
486 return *this;
487 }
489 {
490 *this = operator-(other);
491 return *this;
492 }
494 {
495 *this = operator*(other);
496 return *this;
497 }
499 {
500 *this = operator/(other);
501 return *this;
502 }
503
512 bigfield sqr() const;
513
523 bigfield sqradd(const std::vector<bigfield>& to_add) const;
524
536 bigfield pow(const uint32_t exponent) const;
537
546 bigfield madd(const bigfield& to_mul, const std::vector<bigfield>& to_add) const;
547
549 std::vector<bigfield>& mul_right,
550 const std::vector<bigfield>& to_add);
551
552 static bigfield mult_madd(const std::vector<bigfield>& mul_left,
553 const std::vector<bigfield>& mul_right,
554 const std::vector<bigfield>& to_add,
555 bool fix_remainder_to_zero = false);
556
557 static bigfield dual_madd(const bigfield& left_a,
558 const bigfield& right_a,
559 const bigfield& left_b,
560 const bigfield& right_b,
561 const std::vector<bigfield>& to_add);
562
563 // compute -(mul_left * mul_right + ...to_sub) / (divisor)
564 // We can evaluate this relationship with only one set of quotient/remainder range checks
565 static bigfield msub_div(const std::vector<bigfield>& mul_left,
566 const std::vector<bigfield>& mul_right,
567 const bigfield& divisor,
568 const std::vector<bigfield>& to_sub,
569 bool enable_divisor_nz_check = true);
570
571 static bigfield sum(const std::vector<bigfield>& terms);
572 static bigfield internal_div(const std::vector<bigfield>& numerators,
573 const bigfield& denominator,
574 bool check_for_zero);
575
576 static bigfield div_without_denominator_check(const std::vector<bigfield>& numerators, const bigfield& denominator);
578 static bigfield div_check_denominator_nonzero(const std::vector<bigfield>& numerators, const bigfield& denominator);
579
580 bigfield conditional_negate(const bool_t<Builder>& predicate) const;
581
591 bigfield conditional_select(const bigfield& other, const bool_t<Builder>& predicate) const;
592 static bigfield conditional_assign(const bool_t<Builder>& predicate, const bigfield& lhs, const bigfield& rhs)
593 {
594 return rhs.conditional_select(lhs, predicate);
595 }
596
597 bool_t<Builder> operator==(const bigfield& other) const;
598
599 void assert_is_in_field(std::string const& msg = "bigfield::assert_is_in_field") const;
600 void assert_less_than(const uint256_t& upper_limit, std::string const& msg = "bigfield::assert_less_than") const;
601 void reduce_mod_target_modulus() const;
602 void assert_equal(const bigfield& other, std::string const& msg = "bigfield::assert_equal") const;
603 void assert_is_not_equal(const bigfield& other,
604 std::string const& msg = "bigfield: prime limb diff is zero, but expected non-zero") 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 q 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)) - uint512_t(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 + 3) < n
919 // ==> 2Q + 3 < (log(n) - k - L)
920 // ==> Q < ((log(n) - k - L) - 3) / 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.
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 return ((uint256_t(1) << MAX_UNREDUCED_LIMB_BITS) - uint256_t(1));
938 }
939
940 // If we encounter this maximum value of a limb we stop execution
942
944
945 // For testing purposes only
947
948 private:
955 void unsafe_assert_less_than(const uint256_t& upper_limit,
956 std::string const& msg = "bigfield::unsafe_assert_less_than") const;
957
964 {
965 std::array<uint32_t, NUM_LIMBS> limb_witness_indices;
966 for (size_t i = 0; i < NUM_LIMBS; i++) {
967 limb_witness_indices[i] = binary_basis_limbs[i].element.get_normalized_witness_index();
968 }
969 return limb_witness_indices;
970 }
971
981 const bigfield& b,
982 const std::vector<bigfield>& to_add);
992 const std::vector<uint512_t>& bs,
993 const std::vector<uint512_t>& to_add);
994
1006 const std::vector<uint512_t>& bs_max,
1007 const std::vector<bigfield>& to_add,
1008 const std::vector<uint1024_t>& remainders_max = {
1010
1030 static void unsafe_evaluate_multiply_add(const bigfield& input_left,
1031 const bigfield& input_to_mul,
1032 const std::vector<bigfield>& to_add,
1033 const bigfield& input_quotient,
1034 const std::vector<bigfield>& input_remainders);
1035
1056 const std::vector<bigfield>& input_right,
1057 const std::vector<bigfield>& to_add,
1058 const bigfield& input_quotient,
1059 const std::vector<bigfield>& input_remainders);
1060
1075 static void unsafe_evaluate_square_add(const bigfield& left,
1076 const std::vector<bigfield>& to_add,
1077 const bigfield& quotient,
1078 const bigfield& remainder);
1079
1100 void reduction_check() const;
1101
1108 void sanity_check() const;
1109
1116 {
1118 for (size_t i = 0; i < NUM_LIMBS; i++) {
1119 limb_maximums[i] = binary_basis_limbs[i].maximum_value;
1120 }
1121 return limb_maximums;
1122 }
1123
1138
1139}; // namespace stdlib
1140
1141// NOTE: For testing private functions in bigfield
1143 public:
1144 template <typename bigfield>
1145 static void unsafe_assert_less_than(const bigfield& input, const uint256_t& upper_limit)
1146 {
1147 input.unsafe_assert_less_than(upper_limit);
1148 }
1149
1150 template <typename bigfield>
1151 static void unsafe_evaluate_multiply_add(const bigfield& input_left,
1152 const bigfield& input_to_mul,
1153 const std::vector<bigfield>& to_add,
1154 const bigfield& input_quotient,
1155 const std::vector<bigfield>& input_remainders)
1156 {
1157 bigfield::unsafe_evaluate_multiply_add(input_left, input_to_mul, to_add, input_quotient, input_remainders);
1158 }
1159
1160 template <typename bigfield>
1162 const std::vector<bigfield>& input_right,
1163 const std::vector<bigfield>& to_add,
1164 const bigfield& input_quotient,
1165 const std::vector<bigfield>& input_remainders)
1166 {
1168 input_left, input_right, to_add, input_quotient, input_remainders);
1169 }
1170};
1171
1172template <typename C, typename T> inline std::ostream& operator<<(std::ostream& os, bigfield<T, C> const& v)
1173{
1174 return os << v.get_value();
1175}
1176
1177} // namespace bb::stdlib
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:88
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:163
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:148
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:648
static constexpr uint256_t DEFAULT_MAXIMUM_MOST_SIGNIFICANT_LIMB
Definition bigfield.hpp:322
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:232
static constexpr uint512_t get_maximum_unreduced_value()
Definition bigfield.hpp:764
static constexpr uint256_t get_prohibited_limb_value()
Definition bigfield.hpp:941
static constexpr uint64_t NUM_LIMB_BITS
Definition bigfield.hpp:312
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:592
static constexpr uint64_t MAX_UNREDUCED_LIMB_BITS
Definition bigfield.hpp:928
static constexpr size_t MAXIMUM_SUMMAND_COUNT_LOG
Definition bigfield.hpp:328
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
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)
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:361
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
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:345
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: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:319
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 uint64_t NUM_LAST_LIMB_BITS
Definition bigfield.hpp:313
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
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:493
static constexpr uint512_t negative_prime_modulus_mod_binary_basis
Definition bigfield.hpp:338
static bigfield one()
Definition bigfield.hpp:639
static constexpr uint256_t DEFAULT_MAXIMUM_LIMB
Definition bigfield.hpp:321
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:963
bigfield(const unsigned long long value)
Definition bigfield.hpp:136
static constexpr size_t MAXIMUM_SUMMAND_COUNT
Definition bigfield.hpp:329
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:488
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:337
static constexpr uint256_t modulus
Definition bigfield.hpp:310
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 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
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:324
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.
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:498
bigfield operator-() const
Negation operator, works by subtracting this from zero.
Definition bigfield.hpp:481
static constexpr bool is_composite
Definition bigfield.hpp:325
bigfield operator+=(const bigfield &other)
Definition bigfield.hpp:483
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
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:339
static constexpr uint512_t modulus_u512
Definition bigfield.hpp:311
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:422
bool is_constant() const
Definition field.hpp:407
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: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...
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