Skip to content

Commit 05c5d00

Browse files
committed
test: handle gnark-crypto returning non-malleable signatures
1 parent 4de3fa7 commit 05c5d00

File tree

3 files changed

+15
-9
lines changed

3 files changed

+15
-9
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/blang/semver/v4 v4.0.0
88
github.com/consensys/bavard v0.2.1
99
github.com/consensys/compress v0.2.5
10-
github.com/consensys/gnark-crypto v0.19.3-0.20251114101102-c7c3213680f8
10+
github.com/consensys/gnark-crypto v0.19.3-0.20251114114652-a5d1e2d67d6e
1111
github.com/fxamacker/cbor/v2 v2.9.0
1212
github.com/google/go-cmp v0.7.0
1313
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ github.com/consensys/bavard v0.2.1 h1:i2/ZeLXpp7eblPWzUIWf+dtfBocKQIxuiqy9XZlNSf
6161
github.com/consensys/bavard v0.2.1/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs=
6262
github.com/consensys/compress v0.2.5 h1:gJr1hKzbOD36JFsF1AN8lfXz1yevnJi1YolffY19Ntk=
6363
github.com/consensys/compress v0.2.5/go.mod h1:pyM+ZXiNUh7/0+AUjUf9RKUM6vSH7T/fsn5LLS0j1Tk=
64-
github.com/consensys/gnark-crypto v0.19.3-0.20251114101102-c7c3213680f8 h1:47ph0eGnz4NgmCdROVZvR4tMwwAanu0dsdMdA8DXmuk=
65-
github.com/consensys/gnark-crypto v0.19.3-0.20251114101102-c7c3213680f8/go.mod h1:OgCH7cSoJ46c+nOzvQuwOrIE9fawpXMYOQFzj22Vy3E=
64+
github.com/consensys/gnark-crypto v0.19.3-0.20251114114652-a5d1e2d67d6e h1:+irrCTA6bOfWf3z2+cQCVr3aKdLaPErPpS01ANFWV1k=
65+
github.com/consensys/gnark-crypto v0.19.3-0.20251114114652-a5d1e2d67d6e/go.mod h1:OgCH7cSoJ46c+nOzvQuwOrIE9fawpXMYOQFzj22Vy3E=
6666
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
6767
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
6868
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=

std/evmprecompiles/01-ecrecover_test.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (c *ecrecoverCircuit) Define(api frontend.API) error {
6060
return nil
6161
}
6262

63-
func testRoutineECRecover(t *testing.T, wantStrict bool) (circ, wit *ecrecoverCircuit, largeS bool) {
63+
func testRoutineECRecover(t *testing.T, wantStrict bool, forceLargeS bool) (circ, wit *ecrecoverCircuit, largeS bool) {
6464
halfFr := new(big.Int).Sub(fr.Modulus(), big.NewInt(1))
6565
halfFr.Div(halfFr, big.NewInt(2))
6666

@@ -77,6 +77,12 @@ func testRoutineECRecover(t *testing.T, wantStrict bool) (circ, wit *ecrecoverCi
7777
if err != nil {
7878
t.Fatal("sign", err)
7979
}
80+
// SignForRecover always returns s < r_mod/2. But in the tests we want
81+
// to check that the circuit fails when s > r_mod/2 in strict mode.
82+
if forceLargeS && s.Cmp(halfFr) <= 0 {
83+
s.Sub(fr.Modulus(), s)
84+
}
85+
8086
if !wantStrict || halfFr.Cmp(s) > 0 {
8187
break
8288
}
@@ -103,14 +109,14 @@ func testRoutineECRecover(t *testing.T, wantStrict bool) (circ, wit *ecrecoverCi
103109

104110
func TestECRecoverCircuitShortStrict(t *testing.T) {
105111
assert := test.NewAssert(t)
106-
circuit, witness, _ := testRoutineECRecover(t, true)
112+
circuit, witness, _ := testRoutineECRecover(t, true, false)
107113
err := test.IsSolved(circuit, witness, ecc.BN254.ScalarField())
108114
assert.NoError(err)
109115
}
110116

111117
func TestECRecoverCircuitShortLax(t *testing.T) {
112118
assert := test.NewAssert(t)
113-
circuit, witness, _ := testRoutineECRecover(t, false)
119+
circuit, witness, _ := testRoutineECRecover(t, false, false)
114120
err := test.IsSolved(circuit, witness, ecc.BN254.ScalarField())
115121
assert.NoError(err)
116122
}
@@ -122,7 +128,7 @@ func TestECRecoverCircuitShortMismatch(t *testing.T) {
122128
var circuit, witness *ecrecoverCircuit
123129
var largeS bool
124130
for {
125-
circuit, witness, largeS = testRoutineECRecover(t, false)
131+
circuit, witness, largeS = testRoutineECRecover(t, false, true)
126132
if largeS {
127133
witness.Strict = 1
128134
break
@@ -134,7 +140,7 @@ func TestECRecoverCircuitShortMismatch(t *testing.T) {
134140

135141
func TestECRecoverCircuitFull(t *testing.T) {
136142
assert := test.NewAssert(t)
137-
circuit, witness, _ := testRoutineECRecover(t, false)
143+
circuit, witness, _ := testRoutineECRecover(t, false, false)
138144

139145
assert.CheckCircuit(
140146
circuit,
@@ -256,7 +262,7 @@ func TestECRecoverInfinityWoFailure(t *testing.T) {
256262

257263
func TestInvalidFailureTag(t *testing.T) {
258264
assert := test.NewAssert(t)
259-
circuit, witness, _ := testRoutineECRecover(t, false)
265+
circuit, witness, _ := testRoutineECRecover(t, false, false)
260266
witness.IsFailure = 1
261267
err := test.IsSolved(circuit, witness, ecc.BN254.ScalarField())
262268
assert.Error(err)

0 commit comments

Comments
 (0)