binius_circuits/ecdsa/
ecrecover.rs1use binius_frontend::{CircuitBuilder, Wire};
4
5use super::scalar_mul::{MSM_WINDOW, msm_strauss_endo};
6use crate::{
7 bignum::{BigUint, biguint_lt},
8 secp256k1::{Secp256k1, Secp256k1Affine, coord_zero},
9 util::all_true,
10};
11
12pub fn ecrecover(
26 b: &CircuitBuilder,
27 z: &BigUint,
28 r: &BigUint,
29 s: &BigUint,
30 recid_odd: Wire,
31) -> Secp256k1Affine {
32 let curve = Secp256k1::new(b);
33
34 let nonce = curve.recover(b, r, recid_odd);
35 let nonce_not_pai = b.bnot(nonce.is_point_at_infinity);
36
37 let f_scalar = curve.f_scalar();
38 let valid_r = b.band(b.bnot(r.is_zero(b)), biguint_lt(b, r, f_scalar.modulus()));
39 let valid_s = b.band(b.bnot(s.is_zero(b)), biguint_lt(b, s, f_scalar.modulus()));
40
41 let u1 = f_scalar.sub(b, &coord_zero(b), &f_scalar.div(b, z, r, valid_r));
44 let u2 = f_scalar.div(b, s, r, valid_r);
45
46 let g = Secp256k1Affine::generator(b);
48 let recovered_pk = msm_strauss_endo(b, &curve, MSM_WINDOW, &[u1, u2], &[g, nonce]);
49
50 let conditions = [valid_r, valid_s, nonce_not_pai];
51 recovered_pk.pai_unless(b, all_true(b, conditions))
52}