Skip to content

Commit 87f846d

Browse files
forkfuryivokub
andauthored
fix: improve AssertIsCrumb readability and add constant check (#1650)
Co-authored-by: Ivo Kubjas <[email protected]>
1 parent ad8dda7 commit 87f846d

File tree

4 files changed

+37
-7
lines changed

4 files changed

+37
-7
lines changed

frontend/cs/r1cs/api_assertions.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,18 @@ func (builder *builder[E]) AssertIsBoolean(i1 frontend.Variable) {
7878
}
7979

8080
func (builder *builder[E]) AssertIsCrumb(i1 frontend.Variable) {
81-
i1 = builder.MulAcc(builder.Mul(-3, i1), i1, i1)
82-
i1 = builder.MulAcc(builder.Mul(2, i1), i1, i1)
83-
builder.AssertIsEqual(i1, 0)
81+
if c, ok := builder.constantValue(i1); ok {
82+
if i, ok := builder.cs.Uint64(c); ok && i < 4 {
83+
return
84+
}
85+
panic(fmt.Sprintf("AssertIsCrumb constant input %s is not a crumb", builder.cs.String(c)))
86+
}
87+
88+
// i1 (i1-1) (i1-2) (i1-3) = (i1² - 3i1) (i1² - 3i1 + 2)
89+
// take X := i1² - 3i1 and we get X (X+2) = 0
90+
x := builder.MulAcc(builder.Mul(-3, i1), i1, i1)
91+
x = builder.MulAcc(builder.Mul(2, x), x, x)
92+
builder.AssertIsEqual(x, 0)
8493
}
8594

8695
// AssertIsLessOrEqual adds assertion in constraint builder (v ⩽ bound)

frontend/cs/scs/api_assertions.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,21 +119,24 @@ func (builder *builder[E]) AssertIsBoolean(i1 frontend.Variable) {
119119
}
120120

121121
func (builder *builder[E]) AssertIsCrumb(i1 frontend.Variable) {
122-
const errorMsg = "AssertIsCrumb: input is not a crumb"
123122
if c, ok := builder.constantValue(i1); ok {
124123
if i, ok := builder.cs.Uint64(c); ok && i < 4 {
125124
return
126125
}
127-
panic(errorMsg)
126+
panic(fmt.Sprintf("AssertIsCrumb constant input %s is not a crumb", builder.cs.String(c)))
128127
}
129128

130129
// i1 (i1-1) (i1-2) (i1-3) = (i1² - 3i1) (i1² - 3i1 + 2)
131130
// take X := i1² - 3i1 and we get X (X+2) = 0
132131

132+
// usually MulAcc is a composition in PLONK, unless we have the condition
133+
// a/c == const. This holds here so this is only a single constraint.
133134
x := builder.MulAcc(builder.Mul(-3, i1), i1, i1).(expr.Term[E])
134135

135-
// TODO @Tabaie Ideally this entire function would live in std/math/bits as it is quite specialized;
136-
// however using two generic MulAccs and an AssertIsEqual results in three constraints rather than two.
136+
// usually bit assertions are defined in [std/math/bits] package, but we
137+
// already have it and want to keep it backwards compatible. By doing it
138+
// directly we can avoid a constraint as we do 2X + X^2 == 0 in a single
139+
// constraint.
137140
builder.addPlonkConstraint(sparseR1C[E]{
138141
xa: x.VID,
139142
xb: x.VID,

internal/stats/latest_stats.csv

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
circuit,curve,backend,nbConstraints,nbWires
2+
api/AssertIsCrumb,bn254,groth16,3,2
3+
api/AssertIsCrumb,bls12_377,groth16,3,2
4+
api/AssertIsCrumb,bls12_381,groth16,3,2
5+
api/AssertIsCrumb,bls24_315,groth16,3,2
6+
api/AssertIsCrumb,bls24_317,groth16,3,2
7+
api/AssertIsCrumb,bw6_761,groth16,3,2
8+
api/AssertIsCrumb,bw6_633,groth16,3,2
9+
api/AssertIsCrumb,bn254,plonk,2,1
10+
api/AssertIsCrumb,bls12_377,plonk,2,1
11+
api/AssertIsCrumb,bls12_381,plonk,2,1
12+
api/AssertIsCrumb,bls24_315,plonk,2,1
13+
api/AssertIsCrumb,bls24_317,plonk,2,1
14+
api/AssertIsCrumb,bw6_761,plonk,2,1
15+
api/AssertIsCrumb,bw6_633,plonk,2,1
216
api/AssertIsLessOrEqual,bn254,groth16,1523,1367
317
api/AssertIsLessOrEqual,bls12_377,groth16,1517,1349
418
api/AssertIsLessOrEqual,bls12_381,groth16,1529,1405

internal/stats/snippet.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ func initSnippets() {
5959
api.AssertIsLessOrEqual(newVariable(), bound)
6060
})
6161

62+
registerSnippet("api/AssertIsCrumb", func(api frontend.API, newVariable func() frontend.Variable) {
63+
api.AssertIsCrumb(newVariable())
64+
})
65+
6266
// add std snippets
6367
registerSnippet("math/bits.ToBinary", func(api frontend.API, newVariable func() frontend.Variable) {
6468
_ = bits.ToBinary(api, newVariable())

0 commit comments

Comments
 (0)