Skip to content

Commit

Permalink
refactor: emulated clean up fixes #448 (#449)
Browse files Browse the repository at this point in the history
* refactor: step 1 clean up api and builder wrapper

* refactor: PackElementLimbs PackFull -> packLimbs

* refactor: added field.NewElement

* refactor: remove deadcode from builder stuff, update stats with constraining inputs

* build: restore golangci-lint conf

* refactor: emulated.NewConstant -> emulated.FromConstant

* refactor: emulated.FromConstant -> emulated.ValueOf

* fix: ensure we alwways constrain witness limbs

* fix: fix optimisation test bound with constrained limbs

* perf: constraint to modulus width the witness limbs
  • Loading branch information
gbotrel authored Jan 27, 2023
1 parent 8a39609 commit 3f4cefa
Show file tree
Hide file tree
Showing 25 changed files with 226 additions and 1,270 deletions.
6 changes: 3 additions & 3 deletions examples/emulated/emulated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ func TestEmulatedArithmetic(t *testing.T) {

var circuit, witness Circuit

witness.X = emulated.NewElement[emulated.Secp256k1Fp]("26959946673427741531515197488526605382048662297355296634326893985793")
witness.Y = emulated.NewElement[emulated.Secp256k1Fp]("53919893346855483063030394977053210764097324594710593268653787971586")
witness.Res = emulated.NewElement[emulated.Secp256k1Fp]("485279052387156144224396168012515269674445015885648619762653195154800")
witness.X = emulated.ValueOf[emulated.Secp256k1Fp]("26959946673427741531515197488526605382048662297355296634326893985793")
witness.Y = emulated.ValueOf[emulated.Secp256k1Fp]("53919893346855483063030394977053210764097324594710593268653787971586")
witness.Res = emulated.ValueOf[emulated.Secp256k1Fp]("485279052387156144224396168012515269674445015885648619762653195154800")

assert.ProverSucceeded(&circuit, &witness, test.WithCurves(ecc.BN254), test.WithBackends(backend.GROTH16), test.NoSerialization())
}
5 changes: 0 additions & 5 deletions frontend/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package frontend

import (
"math/big"
"reflect"

"github.com/consensys/gnark/backend/hint"
"github.com/consensys/gnark/constraint"
Expand Down Expand Up @@ -66,10 +65,6 @@ type Builder interface {
// Compile is called after circuit.Define() to produce a final IR (ConstraintSystem)
Compile() (constraint.ConstraintSystem, error)

// VariableCount returns the number of native elements required to represent
// the given reflected type as a witness.
VariableCount(reflect.Type) int

// PublicVariable is called by the compiler when parsing the circuit schema. It panics if
// called inside circuit.Define()
PublicVariable(schema.LeafInfo) Variable
Expand Down
22 changes: 1 addition & 21 deletions frontend/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func Compile(field *big.Int, newBuilder NewBuilder, circuit Circuit, opts ...Com
log := logger.Logger()
log.Info().Msg("compiling circuit")
// parse options
opt := CompileConfig{wrapper: func(b Builder) Builder { return b }}
opt := CompileConfig{}
for _, o := range opts {
if err := o(&opt); err != nil {
log.Err(err).Msg("applying compile option")
Expand All @@ -50,7 +50,6 @@ func Compile(field *big.Int, newBuilder NewBuilder, circuit Circuit, opts ...Com
log.Err(err).Msg("instantiating builder")
return nil, fmt.Errorf("new compiler: %w", err)
}
builder = opt.wrapper(builder)

// parse the circuit builds a schema of the circuit
// and call circuit.Define() method to initialize a list of constraints in the compiler
Expand All @@ -75,11 +74,6 @@ func parseCircuit(builder Builder, circuit Circuit) (err error) {
return err
}

// we scale the number of secret and public variables by n;
// scs and r1cs builder always return 1. Emulated arithmetic returns number of limbs per variable.
n := builder.VariableCount(nil)
s.Public *= n
s.Secret *= n
log := logger.Logger()
log.Info().Int("nbSecret", s.Secret).Int("nbPublic", s.Public).Msg("parsed circuit inputs")

Expand Down Expand Up @@ -140,7 +134,6 @@ type CompileOption func(opt *CompileConfig) error
type CompileConfig struct {
Capacity int
IgnoreUnconstrainedInputs bool
wrapper BuilderWrapper
CompressThreshold int
}

Expand Down Expand Up @@ -168,19 +161,6 @@ func IgnoreUnconstrainedInputs() CompileOption {
}
}

// BuilderWrapper wraps existing Builder.
type BuilderWrapper func(Builder) Builder

// WithBuilderWrapper is a compile option which wraps the builder before parsing
// the schema and calling Define method of the circuit. If not set, then the
// builder returned by the NewBuilder is directly used.
func WithBuilderWrapper(wrapper BuilderWrapper) CompileOption {
return func(opt *CompileConfig) error {
opt.wrapper = wrapper
return nil
}
}

// WithCompressThreshold is a compile option which enforces automatic variable
// compression if the length of the linear expression in the variable exceeds
// given threshold.
Expand Down
5 changes: 0 additions & 5 deletions frontend/cs/r1cs/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,6 @@ func (builder *builder) newInternalVariable() expr.LinearExpression {
return expr.NewLinearExpression(idx, builder.tOne)
}

func (builder *builder) VariableCount(t reflect.Type) int {
// TODO @gbotrel refactor?
return 1
}

// PublicVariable creates a new public Variable
func (builder *builder) PublicVariable(f schema.LeafInfo) frontend.Variable {
idx := builder.cs.AddPublicVariable(f.FullName())
Expand Down
4 changes: 0 additions & 4 deletions frontend/cs/scs/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,6 @@ func (builder *scs) newInternalVariable() expr.TermToRefactor {
return expr.NewTermToRefactor(idx, constraint.CoeffIdOne)
}

func (builder *scs) VariableCount(t reflect.Type) int {
return 1
}

// PublicVariable creates a new Public Variable
func (builder *scs) PublicVariable(f schema.LeafInfo) frontend.Variable {
idx := builder.cs.AddPublicVariable(f.FullName())
Expand Down
Binary file modified internal/stats/latest.stats
Binary file not shown.
25 changes: 15 additions & 10 deletions internal/stats/snippet.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,27 @@ func initSnippets() {
_ = mimc.Sum()
})
registerSnippet("math/emulated/secp256k1_64", func(api frontend.API, newVariable func() frontend.Variable) {
secp256k1, _ := emulated.NewAPI[emulated.Secp256k1Fp](api)
secp256k1, _ := emulated.NewField[emulated.Secp256k1Fp](api)

newElement := func() emulated.Element[emulated.Secp256k1Fp] {
r := emulated.NewElement[emulated.Secp256k1Fp](nil)
for i := 0; i < len(r.Limbs); i++ {
r.Limbs[i] = newVariable()
newElement := func() *emulated.Element[emulated.Secp256k1Fp] {
limbs := make([]frontend.Variable, emulated.Secp256k1Fp{}.NbLimbs())
for i := 0; i < len(limbs); i++ {
limbs[i] = newVariable()
}
return r
return secp256k1.NewElement(limbs)
}

x13 := secp256k1.Mul(newElement(), newElement(), newElement())
fx2 := secp256k1.Mul(5, newElement())
x13 := secp256k1.Mul(newElement(), newElement())
x13 = secp256k1.Mul(x13, newElement())
five := emulated.ValueOf[emulated.Secp256k1Fp](5)
fx2 := secp256k1.Mul(&five, newElement())
nom := secp256k1.Sub(fx2, x13)
denom := secp256k1.Add(newElement(), newElement(), newElement(), newElement())
denom := secp256k1.Add(newElement(), newElement())
denom = secp256k1.Add(denom, newElement())
denom = secp256k1.Add(denom, newElement())
free := secp256k1.Div(nom, denom)
res := secp256k1.Add(x13, fx2, free)
res := secp256k1.Add(x13, fx2)
res = secp256k1.Add(res, free)
secp256k1.AssertIsEqual(res, newElement())
})

Expand Down
8 changes: 4 additions & 4 deletions std/algebra/weierstrass/doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ func (c *ExampleCurveCircuit[B, S]) Define(api frontend.API) error {
panic("initalize new curve")
}
G := curve.Generator()
scalar4 := emulated.NewElement[S](4)
scalar4 := emulated.ValueOf[S](4)
g4 := curve.ScalarMul(G, &scalar4) // 4*G
scalar5 := emulated.NewElement[S](5)
scalar5 := emulated.ValueOf[S](5)
g5 := curve.ScalarMul(G, &scalar5) // 5*G
g9 := curve.Add(g4, g5) // 9*G
curve.AssertIsEqual(g9, &c.Res)
Expand All @@ -41,8 +41,8 @@ func ExampleCurve() {
circuit := ExampleCurveCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{}
witness := ExampleCurveCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{
Res: weierstrass.AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gy),
X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy),
},
}
ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
Expand Down
6 changes: 3 additions & 3 deletions std/algebra/weierstrass/point.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func New[Base, Scalars emulated.FieldParams](api frontend.API, params CurveParam
if err != nil {
return nil, fmt.Errorf("new scalar api: %w", err)
}
Gx := emulated.NewElement[Base](params.Gx)
Gy := emulated.NewElement[Base](params.Gy)
Gx := emulated.ValueOf[Base](params.Gx)
Gy := emulated.ValueOf[Base](params.Gy)
return &Curve[Base, Scalars]{
params: params,
api: api,
Expand All @@ -32,7 +32,7 @@ func New[Base, Scalars emulated.FieldParams](api frontend.API, params CurveParam
X: Gx,
Y: Gy,
},
a: emulated.NewElement[Base](params.A),
a: emulated.ValueOf[Base](params.A),
addA: params.A.Cmp(big.NewInt(0)) != 0,
}, nil
}
Expand Down
48 changes: 24 additions & 24 deletions std/algebra/weierstrass/point_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ func TestNeg(t *testing.T) {
circuit := NegTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{}
witness := NegTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{
P: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gy),
X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy),
},
Q: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.NewElement[emulated.Secp256k1Fp](yn),
X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.ValueOf[emulated.Secp256k1Fp](yn),
},
}
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
Expand Down Expand Up @@ -70,16 +70,16 @@ func TestAdd(t *testing.T) {
circuit := AddTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{}
witness := AddTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{
P: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gy),
X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy),
},
Q: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](xd),
Y: emulated.NewElement[emulated.Secp256k1Fp](yd),
X: emulated.ValueOf[emulated.Secp256k1Fp](xd),
Y: emulated.ValueOf[emulated.Secp256k1Fp](yd),
},
R: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](xa),
Y: emulated.NewElement[emulated.Secp256k1Fp](ya),
X: emulated.ValueOf[emulated.Secp256k1Fp](xa),
Y: emulated.ValueOf[emulated.Secp256k1Fp](ya),
},
}
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
Expand Down Expand Up @@ -107,12 +107,12 @@ func TestDouble(t *testing.T) {
circuit := DoubleTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{}
witness := DoubleTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{
P: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gy),
X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy),
},
Q: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](xd),
Y: emulated.NewElement[emulated.Secp256k1Fp](yd),
X: emulated.ValueOf[emulated.Secp256k1Fp](xd),
Y: emulated.ValueOf[emulated.Secp256k1Fp](yd),
},
}
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
Expand Down Expand Up @@ -143,14 +143,14 @@ func TestScalarMul(t *testing.T) {

circuit := ScalarMulTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{}
witness := ScalarMulTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{
S: emulated.NewElement[emulated.Secp256k1Fr](s),
S: emulated.ValueOf[emulated.Secp256k1Fr](s),
P: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.NewElement[emulated.Secp256k1Fp](secpCurve.Gy),
X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx),
Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy),
},
Q: AffinePoint[emulated.Secp256k1Fp]{
X: emulated.NewElement[emulated.Secp256k1Fp](sx),
Y: emulated.NewElement[emulated.Secp256k1Fp](sy),
X: emulated.ValueOf[emulated.Secp256k1Fp](sx),
Y: emulated.ValueOf[emulated.Secp256k1Fp](sy),
},
}
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
Expand All @@ -169,14 +169,14 @@ func TestScalarMul2(t *testing.T) {

circuit := ScalarMulTest[emulated.BN254Fp, emulated.BN254Fr]{}
witness := ScalarMulTest[emulated.BN254Fp, emulated.BN254Fr]{
S: emulated.NewElement[emulated.BN254Fr](s),
S: emulated.ValueOf[emulated.BN254Fr](s),
P: AffinePoint[emulated.BN254Fp]{
X: emulated.NewElement[emulated.BN254Fp](gen.X.BigInt(new(big.Int))),
Y: emulated.NewElement[emulated.BN254Fp](gen.Y.BigInt(new(big.Int))),
X: emulated.ValueOf[emulated.BN254Fp](gen.X.BigInt(new(big.Int))),
Y: emulated.ValueOf[emulated.BN254Fp](gen.Y.BigInt(new(big.Int))),
},
Q: AffinePoint[emulated.BN254Fp]{
X: emulated.NewElement[emulated.BN254Fp](res.X.BigInt(new(big.Int))),
Y: emulated.NewElement[emulated.BN254Fp](res.Y.BigInt(new(big.Int))),
X: emulated.ValueOf[emulated.BN254Fp](res.X.BigInt(new(big.Int))),
Y: emulated.ValueOf[emulated.BN254Fp](res.Y.BigInt(new(big.Int))),
},
}
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
Expand Down
1 change: 1 addition & 0 deletions std/math/emulated/composition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func TestComposition(t *testing.T) {
}

func testComposition[T FieldParams](t *testing.T) {
t.Helper()
assert := test.NewAssert(t)
var fp T
assert.Run(func(assert *test.Assert) {
Expand Down
6 changes: 3 additions & 3 deletions std/math/emulated/doc_example_field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ func (c *ExampleFieldCircuit[T]) Define(api frontend.API) error {
func ExampleField() {
circuit := ExampleFieldCircuit[emulated.BN254Fp]{}
witness := ExampleFieldCircuit[emulated.BN254Fp]{
In1: emulated.NewElement[emulated.BN254Fp](3),
In2: emulated.NewElement[emulated.BN254Fp](5),
Res: emulated.NewElement[emulated.BN254Fp](15),
In1: emulated.ValueOf[emulated.BN254Fp](3),
In2: emulated.ValueOf[emulated.BN254Fp](5),
Res: emulated.ValueOf[emulated.BN254Fp](15),
}
ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
if err != nil {
Expand Down
62 changes: 0 additions & 62 deletions std/math/emulated/doc_example_fieldapi_builder_test.go

This file was deleted.

Loading

0 comments on commit 3f4cefa

Please sign in to comment.