111 using FrNative =
typename G::Fr;
112 using AffineNative =
typename G::affine_element;
113 using ElementNative =
typename G::element;
118 element T1 = element::secp256r1_fixed_base_mul(u1);
130 Fr u2_safe = Fr::conditional_assign(u2_is_degenerate,
Fr(2), u2);
133 const FrNative u2_n(
uint256_t(u2_safe.get_value() % Fr::modulus_u512));
134 const AffineNative pubkey_native = pubkey.
get_value();
135 const AffineNative T2_native(ElementNative(pubkey_native) * u2_n);
154 Fr alpha2_fr(alpha2_field, zero_witness);
155 Fr beta2_abs_fr(beta2_abs_field, zero_witness);
158 Fr neg_beta2_fr = -beta2_abs_fr;
159 Fr beta2_signed_fr = Fr::conditional_assign(beta2_neg, neg_beta2_fr, beta2_abs_fr);
160 (beta2_signed_fr * u2_safe).assert_equal(alpha2_fr,
"secp256r1 fake-GLV: β₂ · u₂ ≠ α₂ (mod n)");
173 element msm = element::batch_mul(
174 { pubkey, T2_msm }, { alpha2_fr, beta2_abs_fr }, 128,
false);
178 return { T1 + T2, !u2_is_degenerate };
210 using AffineNative =
typename G::affine_element;
211 using FqNative =
typename G::Fq;
216 constexpr size_t NUM_WINDOWS = FBT::NUM_WINDOWS;
217 constexpr size_t NUM_WINDOWS_LO = FBT::NUM_WINDOWS_LO;
218 constexpr size_t NUM_WINDOWS_HI = FBT::NUM_WINDOWS_HI;
221 BB_ASSERT(
builder !=
nullptr,
"secp256r1_fixed_base_mul: u must be associated with a circuit context.");
229 const field_ct u_low = u.get_limb(0).element + (u.get_limb(1).element * limb_shift);
230 const field_ct u_high = u.get_limb(2).element + (u.get_limb(3).element * limb_shift);
237 const auto xlo_lo =
read(MultiTableId::SECP256R1_FIXED_BASE_XLO_LO, u_low);
238 const auto xlo_hi =
read(MultiTableId::SECP256R1_FIXED_BASE_XLO_HI, u_high);
239 const auto xhi_lo =
read(MultiTableId::SECP256R1_FIXED_BASE_XHI_LO, u_low);
240 const auto xhi_hi =
read(MultiTableId::SECP256R1_FIXED_BASE_XHI_HI, u_high);
241 const auto ylo_lo =
read(MultiTableId::SECP256R1_FIXED_BASE_YLO_LO, u_low);
242 const auto ylo_hi =
read(MultiTableId::SECP256R1_FIXED_BASE_YLO_HI, u_high);
243 const auto yhi_lo =
read(MultiTableId::SECP256R1_FIXED_BASE_YHI_LO, u_low);
244 const auto yhi_hi =
read(MultiTableId::SECP256R1_FIXED_BASE_YHI_HI, u_high);
251 auto build_element = [&](
const auto& xlo_r,
const auto& xhi_r,
const auto& ylo_r,
const auto& yhi_r,
size_t j) {
252 const Fq x = Fq::unsafe_construct_from_limbs(
253 xlo_r[ColumnIdx::C2][j], xlo_r[ColumnIdx::C3][j], xhi_r[ColumnIdx::C2][j], xhi_r[ColumnIdx::C3][j]);
254 const Fq y = Fq::unsafe_construct_from_limbs(
255 ylo_r[ColumnIdx::C2][j], ylo_r[ColumnIdx::C3][j], yhi_r[ColumnIdx::C2][j], yhi_r[ColumnIdx::C3][j]);
258 for (
size_t j = 0; j < NUM_WINDOWS_LO; ++j) {
259 looked_up[j] = build_element(xlo_lo, xhi_lo, ylo_lo, yhi_lo, j);
261 for (
size_t j = 0; j < NUM_WINDOWS_HI; ++j) {
262 looked_up[NUM_WINDOWS_LO + j] = build_element(xlo_hi, xhi_hi, ylo_hi, yhi_hi, j);
266 auto chain = element::chain_add_start(looked_up[0], looked_up[1]);
267 for (
size_t i = 2; i < NUM_WINDOWS; ++i) {
268 chain = element::chain_add(looked_up[i], chain);
270 const element raw_result = element::chain_add_end(chain);
273 const AffineNative total_offset_affine = FBT::total_offset();
274 const element offset_correction(
Fq(FqNative(total_offset_affine.x)),
275 Fq(FqNative(total_offset_affine.y)),
277 return raw_result - offset_correction;