Skip to main content

binius_circuits/secp256k1/
common.rs

1// Copyright 2025 Irreducible Inc.
2use binius_frontend::CircuitBuilder;
3use hex_literal::hex;
4
5use crate::bignum::{BigUint, PseudoMersennePrimeField};
6
7pub const N_LIMBS: usize = 4;
8
9// Generator X coordinate, big endian.
10const GX_BE: [u8; 32] = hex!("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
11
12// Generator Y coordinate, big endian.
13const GY_BE: [u8; 32] = hex!("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
14
15// ((2^256-2^32-977) + 1)/4 => exponent for finding quadratic residues.
16const POW_SQRT: [u8; 32] = hex!("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFF0C");
17
18// The value `λ` of the endomorphism `λ (x, y) = (βx, y)`, big endian.
19const LAMBDA: [u8; 32] = hex!("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72");
20
21// The value `β` of the endomorphism `λ (x, y) = (βx, y)`, big endian.
22const BETA: [u8; 32] = hex!("7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE");
23
24/// Padded zero.
25pub fn coord_zero(b: &CircuitBuilder) -> BigUint {
26	BigUint::new_constant(b, &num_bigint::BigUint::ZERO).zero_extend(b, N_LIMBS)
27}
28
29/// Zero extended b = 7 constant.
30pub fn coord_b(b: &CircuitBuilder) -> BigUint {
31	BigUint::new_constant(b, &num_bigint::BigUint::from(7usize)).zero_extend(b, N_LIMBS)
32}
33
34/// The value `λ` of the endomorphism `λ (x, y) = (βx, y)`.
35pub fn coord_lambda(b: &CircuitBuilder) -> BigUint {
36	BigUint::new_constant(b, &num_bigint::BigUint::from_bytes_be(&LAMBDA))
37}
38
39/// The value `β` of the endomorphism `λ (x, y) = (βx, y)`.
40pub fn coord_beta(b: &CircuitBuilder) -> BigUint {
41	BigUint::new_constant(b, &num_bigint::BigUint::from_bytes_be(&BETA))
42}
43
44/// Quadratic residue exponent.
45///
46/// Field modulus p = 3 (mod 4) allow raising to the power (p+1)/4 to compute one of quadratic
47/// residues. Another quadratic residue is its additive inverse.
48pub fn pow_sqrt(b: &CircuitBuilder) -> BigUint {
49	BigUint::new_constant(b, &num_bigint::BigUint::from_bytes_be(&POW_SQRT))
50}
51
52/// Coordinates of the generator basepoint.
53pub fn coords_gen(b: &CircuitBuilder) -> (BigUint, BigUint) {
54	let x = BigUint::new_constant(b, &num_bigint::BigUint::from_bytes_be(&GX_BE));
55	let y = BigUint::new_constant(b, &num_bigint::BigUint::from_bytes_be(&GY_BE));
56	(x, y)
57}
58
59/// Coordinate prime field, of modulus `2^256 - 2^32 - 977`.
60pub fn coord_field(b: &CircuitBuilder) -> PseudoMersennePrimeField {
61	PseudoMersennePrimeField::new(b, 256, &[1 << 32 | 977])
62}
63
64/// Scalar prime field, of modulus equal to secp256k1 group size.
65pub fn scalar_field(b: &CircuitBuilder) -> PseudoMersennePrimeField {
66	PseudoMersennePrimeField::new(b, 256, &[0x402da1732fc9bebf, 0x4551231950b75fc4, 1])
67}