diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index b58f8dcd4a..f99c8693a1 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -26,9 +26,9 @@ jobs: if [[ -n $(git status --porcelain) ]]; then echo "git repo is dirty after running go generate -- please don't modify generated files"; echo $(git diff);echo $(git status --porcelain); exit 1; fi - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v8 with: - version: v1.60 + version: v2.1.6 args: -v --timeout=5m test: diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6dcc8a68a0..4601b32ed4 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -29,10 +29,10 @@ jobs: if [[ -n $(git status --porcelain) ]]; then echo "git repo is dirty after running go generate -- please don't modify generated files"; echo $(git diff);echo $(git status --porcelain); exit 1; fi - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v8 with: - version: v1.60 - args: -v --timeout=5m + version: v2.1.6 + args: -v --timeout=5m test: strategy: diff --git a/.golangci.yml b/.golangci.yml index 0a86beffd4..5adbc7a0e7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,19 +1,41 @@ +version: "2" +run: + issues-exit-code: 1 linters: - disable-all: true + default: none enable: - - gofmt - staticcheck - gosec - - gosimple - govet - ineffassign - misspell - -linters-settings: - gosec: - excludes: - - G115 # Conversions from int -> uint etc. -issues: - exclude-generated: disable -run: - issues-exit-code: 1 \ No newline at end of file + settings: + staticcheck: + checks: + - all + - '-QF1003' + - '-QF1008' + - '-ST1003' + gosec: + excludes: + - G115 + exclusions: + generated: disable + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + exclusions: + generated: disable + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/constraint/babybear/solver.go b/constraint/babybear/solver.go index 410fc036ea..384620c93e 100644 --- a/constraint/babybear/solver.go +++ b/constraint/babybear/solver.go @@ -309,7 +309,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -321,7 +321,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -370,26 +370,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U32, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U32]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -398,7 +398,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -406,7 +406,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -420,18 +420,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -451,15 +451,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -468,7 +468,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -507,7 +507,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -520,8 +520,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -534,8 +534,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -557,7 +557,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -578,7 +578,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -589,7 +589,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -602,8 +602,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -622,11 +622,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/babybear/system.go b/constraint/babybear/system.go index 4da35e3027..1dbaaeaae3 100644 --- a/constraint/babybear/system.go +++ b/constraint/babybear/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/bls12-377/solver.go b/constraint/bls12-377/solver.go index f79940e3be..6ead45ac84 100644 --- a/constraint/bls12-377/solver.go +++ b/constraint/bls12-377/solver.go @@ -323,7 +323,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -335,7 +335,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -384,26 +384,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U64, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U64]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -412,7 +412,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -420,7 +420,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -434,18 +434,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -465,15 +465,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -482,7 +482,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -521,7 +521,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -534,8 +534,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -548,8 +548,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -571,7 +571,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -592,7 +592,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -603,7 +603,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -616,8 +616,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -636,11 +636,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/bls12-377/system.go b/constraint/bls12-377/system.go index 94e4dee641..6c8b341d77 100644 --- a/constraint/bls12-377/system.go +++ b/constraint/bls12-377/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/bls12-381/solver.go b/constraint/bls12-381/solver.go index 1bfa4c5884..2f84c1c095 100644 --- a/constraint/bls12-381/solver.go +++ b/constraint/bls12-381/solver.go @@ -323,7 +323,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -335,7 +335,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -384,26 +384,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U64, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U64]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -412,7 +412,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -420,7 +420,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -434,18 +434,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -465,15 +465,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -482,7 +482,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -521,7 +521,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -534,8 +534,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -548,8 +548,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -571,7 +571,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -592,7 +592,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -603,7 +603,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -616,8 +616,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -636,11 +636,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/bls12-381/system.go b/constraint/bls12-381/system.go index 3758d6c927..394a502a88 100644 --- a/constraint/bls12-381/system.go +++ b/constraint/bls12-381/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/bls24-315/solver.go b/constraint/bls24-315/solver.go index 4f5b72c776..a6d5eeda62 100644 --- a/constraint/bls24-315/solver.go +++ b/constraint/bls24-315/solver.go @@ -323,7 +323,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -335,7 +335,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -384,26 +384,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U64, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U64]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -412,7 +412,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -420,7 +420,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -434,18 +434,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -465,15 +465,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -482,7 +482,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -521,7 +521,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -534,8 +534,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -548,8 +548,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -571,7 +571,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -592,7 +592,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -603,7 +603,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -616,8 +616,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -636,11 +636,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/bls24-315/system.go b/constraint/bls24-315/system.go index 13e66c3c84..0df18c2420 100644 --- a/constraint/bls24-315/system.go +++ b/constraint/bls24-315/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/bls24-317/solver.go b/constraint/bls24-317/solver.go index 9462b5d3e4..ddee44f3c5 100644 --- a/constraint/bls24-317/solver.go +++ b/constraint/bls24-317/solver.go @@ -323,7 +323,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -335,7 +335,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -384,26 +384,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U64, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U64]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -412,7 +412,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -420,7 +420,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -434,18 +434,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -465,15 +465,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -482,7 +482,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -521,7 +521,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -534,8 +534,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -548,8 +548,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -571,7 +571,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -592,7 +592,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -603,7 +603,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -616,8 +616,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -636,11 +636,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/bls24-317/system.go b/constraint/bls24-317/system.go index deaa1bf689..67315e8cd1 100644 --- a/constraint/bls24-317/system.go +++ b/constraint/bls24-317/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/bn254/solver.go b/constraint/bn254/solver.go index 4ccc03e7e0..fb8c30b93f 100644 --- a/constraint/bn254/solver.go +++ b/constraint/bn254/solver.go @@ -323,7 +323,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -335,7 +335,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -384,26 +384,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U64, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U64]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -412,7 +412,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -420,7 +420,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -434,18 +434,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -465,15 +465,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -482,7 +482,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -521,7 +521,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -534,8 +534,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -548,8 +548,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -571,7 +571,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -592,7 +592,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -603,7 +603,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -616,8 +616,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -636,11 +636,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/bn254/system.go b/constraint/bn254/system.go index bc7ebbc202..469df29876 100644 --- a/constraint/bn254/system.go +++ b/constraint/bn254/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/bw6-633/solver.go b/constraint/bw6-633/solver.go index 642369791f..a0c4ce0d43 100644 --- a/constraint/bw6-633/solver.go +++ b/constraint/bw6-633/solver.go @@ -323,7 +323,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -335,7 +335,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -384,26 +384,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U64, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U64]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -412,7 +412,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -420,7 +420,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -434,18 +434,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -465,15 +465,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -482,7 +482,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -521,7 +521,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -534,8 +534,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -548,8 +548,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -571,7 +571,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -592,7 +592,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -603,7 +603,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -616,8 +616,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -636,11 +636,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/bw6-633/system.go b/constraint/bw6-633/system.go index fb9bffcdad..d94a9c24d7 100644 --- a/constraint/bw6-633/system.go +++ b/constraint/bw6-633/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/bw6-761/solver.go b/constraint/bw6-761/solver.go index a65445eb4c..5eb3ea861e 100644 --- a/constraint/bw6-761/solver.go +++ b/constraint/bw6-761/solver.go @@ -323,7 +323,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -335,7 +335,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -384,26 +384,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U64, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U64]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -412,7 +412,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -420,7 +420,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -434,18 +434,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -465,15 +465,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -482,7 +482,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -521,7 +521,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -534,8 +534,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -548,8 +548,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -571,7 +571,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -592,7 +592,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -603,7 +603,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -616,8 +616,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -636,11 +636,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/bw6-761/system.go b/constraint/bw6-761/system.go index 30f4ee7162..0047cbccfb 100644 --- a/constraint/bw6-761/system.go +++ b/constraint/bw6-761/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/core.go b/constraint/core.go index bc04d580ec..f49d79a8f3 100644 --- a/constraint/core.go +++ b/constraint/core.go @@ -220,7 +220,7 @@ func (system *System) Field() *big.Int { return new(big.Int).Set(system.q) } -// bitLen returns the number of bits needed to represent a fr.Element +// FieldBitLen returns the number of bits needed to represent a fr.Element func (system *System) FieldBitLen() int { return system.bitLen } @@ -344,28 +344,28 @@ func (system *System) VariableToString(vID int) string { return fmt.Sprintf("v%d", vID) // TODO @gbotrel vs strconv.Itoa. } -func (cs *System) AddR1C(c R1C, bID BlueprintID) int { +func (system *System) AddR1C(c R1C, bID BlueprintID) int { profile.RecordConstraint() - blueprint := cs.Blueprints[bID] + blueprint := system.Blueprints[bID] // get a []uint32 from a pool calldata := getBuffer() // compress the R1C into a []uint32 and add the instruction blueprint.(BlueprintR1C).CompressR1C(&c, calldata) - cs.AddInstruction(bID, *calldata) + system.AddInstruction(bID, *calldata) // release the []uint32 to the pool putBuffer(calldata) - return cs.NbConstraints - 1 + return system.NbConstraints - 1 } -func (cs *System) AddSparseR1C(c SparseR1C, bID BlueprintID) int { +func (system *System) AddSparseR1C(c SparseR1C, bID BlueprintID) int { profile.RecordConstraint() - blueprint := cs.Blueprints[bID] + blueprint := system.Blueprints[bID] // get a []uint32 from a pool calldata := getBuffer() @@ -373,75 +373,75 @@ func (cs *System) AddSparseR1C(c SparseR1C, bID BlueprintID) int { // compress the SparceR1C into a []uint32 and add the instruction blueprint.(BlueprintSparseR1C).CompressSparseR1C(&c, calldata) - cs.AddInstruction(bID, *calldata) + system.AddInstruction(bID, *calldata) // release the []uint32 to the pool putBuffer(calldata) - return cs.NbConstraints - 1 + return system.NbConstraints - 1 } -func (cs *System) AddInstruction(bID BlueprintID, calldata []uint32) []uint32 { +func (system *System) AddInstruction(bID BlueprintID, calldata []uint32) []uint32 { // set the offsets pi := PackedInstruction{ - StartCallData: uint64(len(cs.CallData)), - ConstraintOffset: uint32(cs.NbConstraints), - WireOffset: uint32(cs.NbInternalVariables + cs.GetNbPublicVariables() + cs.GetNbSecretVariables()), + StartCallData: uint64(len(system.CallData)), + ConstraintOffset: uint32(system.NbConstraints), + WireOffset: uint32(system.NbInternalVariables + system.GetNbPublicVariables() + system.GetNbSecretVariables()), BlueprintID: bID, } // append the call data - cs.CallData = append(cs.CallData, calldata...) + system.CallData = append(system.CallData, calldata...) // update the total number of constraints - blueprint := cs.Blueprints[pi.BlueprintID] - cs.NbConstraints += blueprint.NbConstraints() + blueprint := system.Blueprints[pi.BlueprintID] + system.NbConstraints += blueprint.NbConstraints() // add the output wires - inst := pi.Unpack(cs) + inst := pi.Unpack(system) nbOutputs := blueprint.NbOutputs(inst) var wires []uint32 for i := 0; i < nbOutputs; i++ { - wires = append(wires, uint32(cs.AddInternalVariable())) + wires = append(wires, uint32(system.AddInternalVariable())) } // add the instruction - cs.Instructions = append(cs.Instructions, pi) + system.Instructions = append(system.Instructions, pi) // update the instruction dependency tree - level := blueprint.UpdateInstructionTree(inst, cs) - iID := uint32(len(cs.Instructions) - 1) + level := blueprint.UpdateInstructionTree(inst, system) + iID := uint32(len(system.Instructions) - 1) // we can't skip levels, so appending is fine. - if int(level) >= len(cs.Levels) { - cs.Levels = append(cs.Levels, []uint32{iID}) + if int(level) >= len(system.Levels) { + system.Levels = append(system.Levels, []uint32{iID}) } else { - cs.Levels[level] = append(cs.Levels[level], iID) + system.Levels[level] = append(system.Levels[level], iID) } return wires } // GetNbConstraints returns the number of constraints -func (cs *System) GetNbConstraints() int { - return cs.NbConstraints +func (system *System) GetNbConstraints() int { + return system.NbConstraints } -func (cs *System) CheckUnconstrainedWires() error { +func (system *System) CheckUnconstrainedWires() error { // TODO @gbotrel return nil } -func (cs *System) GetR1CIterator() R1CIterator { - return R1CIterator{cs: cs} +func (system *System) GetR1CIterator() R1CIterator { + return R1CIterator{cs: system} } -func (cs *System) GetSparseR1CIterator() SparseR1CIterator { - return SparseR1CIterator{cs: cs} +func (system *System) GetSparseR1CIterator() SparseR1CIterator { + return SparseR1CIterator{cs: system} } -func (cs *System) GetCommitments() Commitments { - return cs.CommitmentInfo +func (system *System) GetCommitments() Commitments { + return system.CommitmentInfo } // bufPool is a pool of buffers used by getBuffer and putBuffer. diff --git a/constraint/koalabear/solver.go b/constraint/koalabear/solver.go index 7e227b1f36..553d0b6e8f 100644 --- a/constraint/koalabear/solver.go +++ b/constraint/koalabear/solver.go @@ -309,7 +309,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -321,7 +321,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -370,26 +370,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U32, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U32]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -398,7 +398,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -406,7 +406,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -420,18 +420,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -451,15 +451,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -468,7 +468,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -507,7 +507,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -520,8 +520,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -534,8 +534,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -557,7 +557,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -578,7 +578,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -589,7 +589,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -602,8 +602,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -622,11 +622,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/koalabear/system.go b/constraint/koalabear/system.go index 90cce6d1fa..03bcfd0898 100644 --- a/constraint/koalabear/system.go +++ b/constraint/koalabear/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/constraint/marshal.go b/constraint/marshal.go index a405799e52..5272b00d76 100644 --- a/constraint/marshal.go +++ b/constraint/marshal.go @@ -14,27 +14,27 @@ import ( // ToBytes serializes the constraint system to a byte slice // This is not meant to be called directly since the constraint.System is embedded in // a "curve-typed" system (e.g. bls12-381.system) -func (cs *System) ToBytes() ([]byte, error) { +func (system *System) ToBytes() ([]byte, error) { // we prepare and write 4 distinct blocks of data; // that allow for a more efficient serialization/deserialization (+ parallelism) var calldata, instructions, levels []byte var g errgroup.Group g.Go(func() error { var err error - calldata, err = cs.calldataToBytes() + calldata, err = system.calldataToBytes() return err }) g.Go(func() error { var err error - instructions, err = cs.instructionsToBytes() + instructions, err = system.instructionsToBytes() return err }) g.Go(func() error { var err error - levels, err = cs.levelsToBytes() + levels, err = system.levelsToBytes() return err }) - body, err := cs.toBytes() + body, err := system.toBytes() if err != nil { return nil, err } @@ -64,7 +64,7 @@ func (cs *System) ToBytes() ([]byte, error) { // FromBytes deserializes the constraint system from a byte slice // This is not meant to be called directly since the constraint.System is embedded in // a "curve-typed" system (e.g. bls12-381.system) -func (cs *System) FromBytes(data []byte) (int, error) { +func (system *System) FromBytes(data []byte) (int, error) { if len(data) < headerLen { return 0, errors.New("invalid data length") } @@ -80,15 +80,15 @@ func (cs *System) FromBytes(data []byte) (int, error) { // read the sections in parallel var g errgroup.Group g.Go(func() error { - return cs.levelsFromBytes(data[headerLen : headerLen+h.levelsLen]) + return system.levelsFromBytes(data[headerLen : headerLen+h.levelsLen]) }) g.Go(func() error { - return cs.instructionsFromBytes(data[headerLen+h.levelsLen : headerLen+h.levelsLen+h.instructionsLen]) + return system.instructionsFromBytes(data[headerLen+h.levelsLen : headerLen+h.levelsLen+h.instructionsLen]) }) g.Go(func() error { - return cs.calldataFromBytes(data[headerLen+h.levelsLen+h.instructionsLen : headerLen+h.levelsLen+h.instructionsLen+h.calldataLen]) + return system.calldataFromBytes(data[headerLen+h.levelsLen+h.instructionsLen : headerLen+h.levelsLen+h.instructionsLen+h.calldataLen]) }) // CBOR decoding of the constraint system (except what we do directly in binary) @@ -103,19 +103,19 @@ func (cs *System) FromBytes(data []byte) (int, error) { } decoder := dm.NewDecoder(bytes.NewReader(data[headerLen+h.levelsLen+h.instructionsLen+h.calldataLen : headerLen+h.levelsLen+h.instructionsLen+h.calldataLen+h.bodyLen])) - if err := decoder.Decode(&cs); err != nil { + if err := decoder.Decode(&system); err != nil { return 0, err } - if err := cs.CheckSerializationHeader(); err != nil { + if err := system.CheckSerializationHeader(); err != nil { return 0, err } - switch v := cs.CommitmentInfo.(type) { + switch v := system.CommitmentInfo.(type) { case *Groth16Commitments: - cs.CommitmentInfo = *v + system.CommitmentInfo = *v case *PlonkCommitments: - cs.CommitmentInfo = *v + system.CommitmentInfo = *v } if err := g.Wait(); err != nil { @@ -125,7 +125,7 @@ func (cs *System) FromBytes(data []byte) (int, error) { return headerLen + int(h.levelsLen) + int(h.instructionsLen) + int(h.calldataLen) + int(h.bodyLen), nil } -func (cs *System) toBytes() ([]byte, error) { +func (system *System) toBytes() ([]byte, error) { // CBOR encoding of the constraint system (except what we do directly in binary) ts := getTagSet() enc, err := cbor.CoreDetEncOptions().EncModeWithTags(ts) @@ -136,7 +136,7 @@ func (cs *System) toBytes() ([]byte, error) { encoder := enc.NewEncoder(buf) // encode our object - err = encoder.Encode(cs) + err = encoder.Encode(system) if err != nil { return nil, err } @@ -172,32 +172,32 @@ func (h *header) fromBytes(buf []byte) { h.bodyLen = binary.LittleEndian.Uint64(buf[24:32]) } -func (cs *System) calldataToBytes() ([]byte, error) { +func (system *System) calldataToBytes() ([]byte, error) { // calldata doesn't compress as well as the other sections; - // it still give a better size to use intcomp.CompressUint32 here, + // it still gives a better size to use intcomp.CompressUint32 here, // and an even better one to use binary.UVarint // but, we keep it simple as it makes deserialization much faster // user is still free to compress the final []byte slice if needed. - buf := make([]byte, 0, 8+len(cs.CallData)*binary.MaxVarintLen32) - buf = binary.LittleEndian.AppendUint64(buf, uint64(len(cs.CallData))) - // binary.LittleEndian.PutUint64(buf, uint64(len(cs.CallData))) - // buf = buf[:8+len(cs.CallData)*4] - for _, v := range cs.CallData { + buf := make([]byte, 0, 8+len(system.CallData)*binary.MaxVarintLen32) + buf = binary.LittleEndian.AppendUint64(buf, uint64(len(system.CallData))) + // binary.LittleEndian.PutUint64(buf, uint64(len(system.CallData))) + // buf = buf[:8+len(system.CallData)*4] + for _, v := range system.CallData { buf = binary.AppendUvarint(buf, uint64(v)) // binary.LittleEndian.PutUint32(buf[8+i*4:8+i*4+4], v) } return buf, nil } -func (cs *System) instructionsToBytes() ([]byte, error) { +func (system *System) instructionsToBytes() ([]byte, error) { // prepare the []uint32 separated slices for the packed instructions - sBlueprintID := make([]uint32, len(cs.Instructions)) - sConstraintOffset := make([]uint32, len(cs.Instructions)) - sWireOffset := make([]uint32, len(cs.Instructions)) - sStartCallData := make([]uint64, len(cs.Instructions)) + sBlueprintID := make([]uint32, len(system.Instructions)) + sConstraintOffset := make([]uint32, len(system.Instructions)) + sWireOffset := make([]uint32, len(system.Instructions)) + sStartCallData := make([]uint64, len(system.Instructions)) // collect them - for i, inst := range cs.Instructions { + for i, inst := range system.Instructions { sBlueprintID[i] = uint32(inst.BlueprintID) sConstraintOffset[i] = inst.ConstraintOffset sWireOffset[i] = inst.WireOffset @@ -208,7 +208,7 @@ func (cs *System) instructionsToBytes() ([]byte, error) { var buf32 []uint32 var err error var buf bytes.Buffer - buf.Grow(4 * len(cs.Instructions) * 3) + buf.Grow(4 * len(system.Instructions) * 3) buf32, err = ioutils.CompressAndWriteUints32(&buf, sBlueprintID, buf32) if err != nil { @@ -231,15 +231,15 @@ func (cs *System) instructionsToBytes() ([]byte, error) { return buf.Bytes(), nil } -func (cs *System) levelsToBytes() ([]byte, error) { +func (system *System) levelsToBytes() ([]byte, error) { // they compress very well due to their nature (sequential integers) var buf32 []uint32 var buf bytes.Buffer var err error - buf.Grow(4 * len(cs.Instructions)) + buf.Grow(4 * len(system.Instructions)) - binary.Write(&buf, binary.LittleEndian, uint64(len(cs.Levels))) - for _, l := range cs.Levels { + binary.Write(&buf, binary.LittleEndian, uint64(len(system.Levels))) + for _, l := range system.Levels { buf32, err = ioutils.CompressAndWriteUints32(&buf, l, buf32) if err != nil { return nil, err @@ -249,7 +249,7 @@ func (cs *System) levelsToBytes() ([]byte, error) { return buf.Bytes(), nil } -func (cs *System) levelsFromBytes(in []byte) error { +func (system *System) levelsFromBytes(in []byte) error { levelsLen := binary.LittleEndian.Uint64(in[:8]) @@ -261,9 +261,9 @@ func (cs *System) levelsFromBytes(in []byte) error { n int ) - cs.Levels = make([][]uint32, levelsLen) - for i := range cs.Levels { - buf32, n, cs.Levels[i], err = ioutils.ReadAndDecompressUints32(in, buf32) + system.Levels = make([][]uint32, levelsLen) + for i := range system.Levels { + buf32, n, system.Levels[i], err = ioutils.ReadAndDecompressUints32(in, buf32) if err != nil { return err } @@ -273,7 +273,7 @@ func (cs *System) levelsFromBytes(in []byte) error { return nil } -func (cs *System) instructionsFromBytes(in []byte) error { +func (system *System) instructionsFromBytes(in []byte) error { // read the packed instructions var ( @@ -304,9 +304,9 @@ func (cs *System) instructionsFromBytes(in []byte) error { } // rebuild the instructions - cs.Instructions = make([]PackedInstruction, len(sBlueprintID)) - for i := range cs.Instructions { - cs.Instructions[i] = PackedInstruction{ + system.Instructions = make([]PackedInstruction, len(sBlueprintID)) + for i := range system.Instructions { + system.Instructions[i] = PackedInstruction{ BlueprintID: BlueprintID(sBlueprintID[i]), ConstraintOffset: sConstraintOffset[i], WireOffset: sWireOffset[i], @@ -317,16 +317,16 @@ func (cs *System) instructionsFromBytes(in []byte) error { return nil } -func (cs *System) calldataFromBytes(buf []byte) error { +func (system *System) calldataFromBytes(buf []byte) error { calldataLen := binary.LittleEndian.Uint64(buf[:8]) - cs.CallData = make([]uint32, calldataLen) + system.CallData = make([]uint32, calldataLen) buf = buf[8:] for i := uint64(0); i < calldataLen; i++ { v, n := binary.Uvarint(buf[:min(len(buf), binary.MaxVarintLen64)]) if n <= 0 { return errors.New("invalid calldata") } - cs.CallData[i] = uint32(v) + system.CallData[i] = uint32(v) buf = buf[n:] } return nil diff --git a/constraint/tinyfield/solver.go b/constraint/tinyfield/solver.go index f36f8a25bc..90a56f98dc 100644 --- a/constraint/tinyfield/solver.go +++ b/constraint/tinyfield/solver.go @@ -309,7 +309,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { } // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -321,7 +321,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -370,26 +370,26 @@ func (s *solver) Read(calldata []uint32) (constraint.U32, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.U32]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -398,7 +398,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint, inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } return nil @@ -406,7 +406,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -420,18 +420,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -451,15 +451,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -468,7 +468,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -507,7 +507,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -520,8 +520,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID], &solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID], &s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -534,8 +534,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -557,7 +557,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -578,7 +578,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -589,7 +589,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -602,8 +602,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -622,11 +622,11 @@ func (r *UnsatisfiedConstraintError) Error() string { return fmt.Sprintf("constraint #%d is not satisfied: %s", r.CID, r.Err.Error()) } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/constraint/tinyfield/system.go b/constraint/tinyfield/system.go index dcad646607..50cdd864a6 100644 --- a/constraint/tinyfield/system.go +++ b/constraint/tinyfield/system.go @@ -289,6 +289,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } diff --git a/examples/rollup/rollup_test.go b/examples/rollup/rollup_test.go index b803390ded..9616ace40e 100644 --- a/examples/rollup/rollup_test.go +++ b/examples/rollup/rollup_test.go @@ -142,7 +142,7 @@ func createAccount(i int) (Account, eddsa.PrivateKey) { acc.balance.SetUint64(uint64(i) + 20) rnd.SetUint64(uint64(i)) src := rand.NewSource(int64(i)) - r := rand.New(src) + r := rand.New(src) //#nosec G404 pkey, err := eddsa.GenerateKey(r) if err != nil { diff --git a/frontend/cs/r1cs/api.go b/frontend/cs/r1cs/api.go index 64fce5c32c..56b8e70f46 100644 --- a/frontend/cs/r1cs/api.go +++ b/frontend/cs/r1cs/api.go @@ -645,7 +645,9 @@ func (builder *builder[E]) printArg(log *constraint.LogEntry, sbb *strings.Build // no variables in nested struct, we use fmt std print function if count == 0 || err != nil { - sbb.WriteString(fmt.Sprint(a)) + if _, err = fmt.Fprint(sbb, a); err != nil { + panic(err) + } return } diff --git a/frontend/cs/r1cs/api_assertions.go b/frontend/cs/r1cs/api_assertions.go index eb8e48dd3e..60d66e9a75 100644 --- a/frontend/cs/r1cs/api_assertions.go +++ b/frontend/cs/r1cs/api_assertions.go @@ -52,7 +52,7 @@ func (builder *builder[E]) AssertIsBoolean(i1 frontend.Variable) { v := builder.toVariable(i1) if b, ok := builder.constantValue(v); ok { - if !(b.IsZero() || builder.isCstOne(b)) { + if !(b.IsZero() || builder.isCstOne(b)) { // nolint QF1001 panic("assertIsBoolean failed: constant is not 0 or 1") // TODO @gbotrel print } return diff --git a/frontend/cs/r1cs/builder.go b/frontend/cs/r1cs/builder.go index 048af05bb6..bee5438f80 100644 --- a/frontend/cs/r1cs/builder.go +++ b/frontend/cs/r1cs/builder.go @@ -232,7 +232,7 @@ func (builder *builder[E]) getLinearExpression(_l interface{}) constraint.Linear // that is not api.AssertIsBoolean. If v is a constant, this is a no-op. func (builder *builder[E]) MarkBoolean(v frontend.Variable) { if b, ok := builder.constantValue(v); ok { - if !(b.IsZero() || builder.isCstOne(b)) { + if !(b.IsZero() || builder.isCstOne(b)) { // nolint QF1001 panic("MarkBoolean called a non-boolean constant") } return @@ -320,7 +320,7 @@ func (builder *builder[E]) constantValue(v frontend.Variable) (E, bool) { if _v[0].Coeff == zero { // fast path for zero comparison to avoid overhead of calling IsZero return zero, true } - if !(_v[0].WireID() == 0) { // public ONE WIRE + if _v[0].WireID() != 0 { // public ONE WIRE return zero, false } return _v[0].Coeff, true diff --git a/frontend/cs/scs/api.go b/frontend/cs/scs/api.go index a3abeaa28a..8f90bd318f 100644 --- a/frontend/cs/scs/api.go +++ b/frontend/cs/scs/api.go @@ -549,7 +549,9 @@ func (builder *builder[E]) printArg(log *constraint.LogEntry, sbb *strings.Build // no variables in nested struct, we use fmt std print function if count == 0 || err != nil { - sbb.WriteString(fmt.Sprint(a)) + if _, err = fmt.Fprint(sbb, a); err != nil { + panic(err) + } return } diff --git a/frontend/cs/scs/api_assertions.go b/frontend/cs/scs/api_assertions.go index 3afc5accb5..e96554bdf5 100644 --- a/frontend/cs/scs/api_assertions.go +++ b/frontend/cs/scs/api_assertions.go @@ -84,10 +84,10 @@ func (builder *builder[E]) AssertIsDifferent(i1, i2 frontend.Variable) { builder.Inverse(s) } -// AssertIsBoolean fails if v != 0 ∥ v != 1 +// AssertIsBoolean fails if v ≠ 0 ∥ v ≠ 1 func (builder *builder[E]) AssertIsBoolean(i1 frontend.Variable) { if c, ok := builder.constantValue(i1); ok { - if !(c.IsZero() || builder.cs.IsOne(c)) { + if !(c.IsZero() || builder.cs.IsOne(c)) { // nolint QF1001 panic(fmt.Sprintf("assertIsBoolean failed: constant(%s)", builder.cs.String(c))) } return diff --git a/go.mod b/go.mod index ca2c6d0489..aa60cf59df 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ toolchain go1.23.8 require ( github.com/bits-and-blooms/bitset v1.22.0 github.com/blang/semver/v4 v4.0.0 - github.com/consensys/bavard v0.1.31-0.20250406004941-2db259e4b582 + github.com/consensys/bavard v0.2.1 github.com/consensys/compress v0.2.5 - github.com/consensys/gnark-crypto v0.18.1-0.20250613145137-bf7ac9d06da2 + github.com/consensys/gnark-crypto v0.18.1-0.20250822182027-0ba437ac1a06 github.com/fxamacker/cbor/v2 v2.8.0 github.com/google/go-cmp v0.7.0 github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a diff --git a/go.sum b/go.sum index 71ea875005..f159b77fa0 100644 --- a/go.sum +++ b/go.sum @@ -57,14 +57,12 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/consensys/bavard v0.1.31-0.20250406004941-2db259e4b582 h1:dTlIwEdFQmldzFf5F6bbTcYWhvnAgZai2g8eq3Wwxqg= -github.com/consensys/bavard v0.1.31-0.20250406004941-2db259e4b582/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= +github.com/consensys/bavard v0.2.1 h1:i2/ZeLXpp7eblPWzUIWf+dtfBocKQIxuiqy9XZlNSfQ= +github.com/consensys/bavard v0.2.1/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= github.com/consensys/compress v0.2.5 h1:gJr1hKzbOD36JFsF1AN8lfXz1yevnJi1YolffY19Ntk= github.com/consensys/compress v0.2.5/go.mod h1:pyM+ZXiNUh7/0+AUjUf9RKUM6vSH7T/fsn5LLS0j1Tk= -github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= -github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= -github.com/consensys/gnark-crypto v0.18.1-0.20250613145137-bf7ac9d06da2 h1:LZlarR2EgBB7NDuCf6A9OS2UUa1RAjV2l7T9C0Wvn1I= -github.com/consensys/gnark-crypto v0.18.1-0.20250613145137-bf7ac9d06da2/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/consensys/gnark-crypto v0.18.1-0.20250822182027-0ba437ac1a06 h1:dw3196AJx5o2xp7b0LK2wk6fzsL7VyL25zRgMXodhBA= +github.com/consensys/gnark-crypto v0.18.1-0.20250822182027-0ba437ac1a06/go.mod h1:rT23F0XSZqE0mUA0+pRtnL56IbPxs6gp4CeRsBk4XS0= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= diff --git a/internal/generator/backend/template/gkr/gate_testing.go.tmpl b/internal/generator/backend/template/gkr/gate_testing.go.tmpl index 534b4b01c8..8c78af347c 100644 --- a/internal/generator/backend/template/gkr/gate_testing.go.tmpl +++ b/internal/generator/backend/template/gkr/gate_testing.go.tmpl @@ -160,7 +160,7 @@ func VerifyGateFunctionDegree(f gkr.GateFunction, claimedDegree, nbIn int) error // Note that the runtime is O(len(X)³) func interpolate(X, Y []{{.ElementType}}) (polynomial.Polynomial, error) { if len(X) != len(Y) { - return nil, errors.New("X and Y must have the same length") + return nil, errors.New("same length expected for X and Y") } // solve the system of equations by Gaussian elimination diff --git a/internal/generator/backend/template/representations/solver.go.tmpl b/internal/generator/backend/template/representations/solver.go.tmpl index fd685e6e21..1b8dd42fe4 100644 --- a/internal/generator/backend/template/representations/solver.go.tmpl +++ b/internal/generator/backend/template/representations/solver.go.tmpl @@ -324,7 +324,7 @@ func (s *solver) logValue(log constraint.LogEntry) string { // divByCoeff sets res = res / t.Coeff -func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { +func (s *solver) divByCoeff(res *fr.Element, cID uint32) { switch cID { case constraint.CoeffIdOne: return @@ -336,7 +336,7 @@ func (solver *solver) divByCoeff(res *fr.Element, cID uint32) { // this is slow, but shouldn't happen as divByCoeff is called to // remove the coeff of an unsolved wire // but unsolved wires are (in gnark frontend) systematically set with a coeff == 1 or -1 - res.Div(res, &solver.Coefficients[cID]) + res.Div(res, &s.Coefficients[cID]) } } @@ -390,26 +390,26 @@ func (s *solver) Read(calldata []uint32) (constraint.{{ .ElementType }}, int) { // processInstruction decodes the instruction and execute blueprint-defined logic. // an instruction can encode a hint, a custom constraint or a generic constraint. -func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { +func (s *solver) processInstruction(pi constraint.PackedInstruction, scratch *scratch) error { // fetch the blueprint - blueprint := solver.Blueprints[pi.BlueprintID] - inst := pi.Unpack(&solver.System) + blueprint := s.Blueprints[pi.BlueprintID] + inst := pi.Unpack(&s.System) cID := inst.ConstraintOffset // here we have 1 constraint in the instruction only - if solver.Type == constraint.SystemR1CS { + if s.Type == constraint.SystemR1CS { if bc, ok := blueprint.(constraint.BlueprintR1C); ok { // TODO @gbotrel we use the solveR1C method for now, having user-defined // blueprint for R1CS would require constraint.Solver interface to add methods // to set a,b,c since it's more efficient to compute these while we solve. bc.DecompressR1C(&scratch.tR1C, inst) - return solver.solveR1C(cID, &scratch.tR1C) + return s.solveR1C(cID, &scratch.tR1C) } } // blueprint declared "I know how to solve this." if bc, ok := blueprint.(constraint.BlueprintSolvable[constraint.{{ .ElementType }}]); ok { - if err := bc.Solve(solver, inst); err != nil { - return solver.wrapErrWithDebugInfo(cID, err) + if err := bc.Solve(s, inst); err != nil { + return s.wrapErrWithDebugInfo(cID, err) } return nil } @@ -418,7 +418,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // TODO @gbotrel may be worth it to move hint logic in blueprint "solve" if bc, ok := blueprint.(constraint.BlueprintHint); ok { bc.DecompressHint(&scratch.tHint,inst) - return solver.solveWithHint(&scratch.tHint) + return s.solveWithHint(&scratch.tHint) } @@ -428,7 +428,7 @@ func (solver *solver) processInstruction(pi constraint.PackedInstruction, scratc // run runs the solver. it return an error if a constraint is not satisfied or if not all wires // were instantiated. -func (solver *solver) run() error { +func (s *solver) run() error { // minWorkPerCPU is the minimum target number of constraint a task should hold // in other words, if a level has less than minWorkPerCPU, it will not be parallelized and executed // sequentially without sync. @@ -442,18 +442,18 @@ func (solver *solver) run() error { // then we check that the constraint is valid // if a[i] * b[i] != c[i]; it means the constraint is not satisfied var wg sync.WaitGroup - chTasks := make(chan []uint32, solver.nbTasks) - chError := make(chan error, solver.nbTasks) + chTasks := make(chan []uint32, s.nbTasks) + chError := make(chan error, s.nbTasks) // start a worker pool // each worker wait on chTasks // a task is a slice of constraint indexes to be solved - for i := 0; i < solver.nbTasks; i++ { + for i := 0; i < s.nbTasks; i++ { go func() { var scratch scratch for t := range chTasks { for _, i := range t { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { chError <- err wg.Done() return @@ -473,15 +473,15 @@ func (solver *solver) run() error { var scratch scratch // for each level, we push the tasks - for _, level := range solver.Levels { + for _, level := range s.Levels { // max CPU to use maxCPU := float64(len(level)) / minWorkPerCPU - if maxCPU <= 1.0 || solver.nbTasks == 1 { + if maxCPU <= 1.0 || s.nbTasks == 1 { // we do it sequentially for _, i := range level { - if err := solver.processInstruction(solver.Instructions[i], &scratch); err != nil { + if err := s.processInstruction(s.Instructions[i], &scratch); err != nil { return err } } @@ -490,7 +490,7 @@ func (solver *solver) run() error { // number of tasks for this level is set to number of CPU // but if we don't have enough work for all our CPU, it can be lower. - nbTasks := solver.nbTasks + nbTasks := s.nbTasks maxTasks := int(math.Ceil(maxCPU)) if nbTasks > maxTasks { nbTasks = maxTasks @@ -530,7 +530,7 @@ func (solver *solver) run() error { } } - if int(solver.nbSolved) != len(solver.values) { + if int(s.nbSolved) != len(s.values) { return errors.New("solver didn't assign a value to all wires") } @@ -545,8 +545,8 @@ func (solver *solver) run() error { // returns false, nil if there was no wire to solve // returns true, nil if exactly one wire was solved. In that case, it is redundant to check that // the constraint is satisfied later. -func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { - a, b, c := &solver.a[cID],&solver.b[cID], &solver.c[cID] +func (s *solver) solveR1C(cID uint32, r *constraint.R1C) error { + a, b, c := &s.a[cID],&s.b[cID], &s.c[cID] // the index of the non-zero entry shows if L, R or O has an uninstantiated wire // the content is the ID of the wire non instantiated @@ -559,8 +559,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { vID := t.WireID() // wire is already computed, we just accumulate in val - if solver.solved[vID] { - solver.accumulateInto(t, val) + if s.solved[vID] { + s.accumulateInto(t, val) continue } @@ -584,7 +584,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // or if we solved the unsolved wires with hint functions var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } return nil } @@ -606,7 +606,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // we didn't actually ensure that a * b == c var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 2: @@ -617,7 +617,7 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { } else { var check fr.Element if !check.Mul(a, b).Equal(c) { - return solver.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) + return s.wrapErrWithDebugInfo(cID, fmt.Errorf("%s ⋅ %s != %s", a.String(), b.String(), c.String())) } } case 3: @@ -630,8 +630,8 @@ func (solver *solver) solveR1C(cID uint32, r *constraint.R1C) error { // wire is the term (coeff * value) // but in the solver we want to store the value only // note that in gnark frontend, coeff here is always 1 or -1 - solver.divByCoeff(&wire, termToCompute.CID) - solver.set(wID, wire) + s.divByCoeff(&wire, termToCompute.CID) + s.set(wID, wire) return nil } @@ -651,11 +651,11 @@ func (r *UnsatisfiedConstraintError) Error() string { } -func (solver *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { +func (s *solver) wrapErrWithDebugInfo(cID uint32, err error) *UnsatisfiedConstraintError { var debugInfo *string - if dID, ok := solver.MDebug[int(cID)]; ok { + if dID, ok := s.MDebug[int(cID)]; ok { debugInfo = new(string) - *debugInfo = solver.logValue(solver.DebugInfo[dID]) + *debugInfo = s.logValue(s.DebugInfo[dID]) } return &UnsatisfiedConstraintError{CID: int(cID), Err: err, DebugInfo: debugInfo} } diff --git a/internal/generator/backend/template/representations/system.go.tmpl b/internal/generator/backend/template/representations/system.go.tmpl index 07dc757fd5..c8545e54e5 100644 --- a/internal/generator/backend/template/representations/system.go.tmpl +++ b/internal/generator/backend/template/representations/system.go.tmpl @@ -294,7 +294,6 @@ func (t *SparseR1CSSolution) ReadFrom(r io.Reader) (int64, error) { return n, err } - -func (s *system) AddGkr(gkr gkrinfo.StoringInfo) error { - return s.System.AddGkr(gkr) +func (cs *system) AddGkr(gkr gkrinfo.StoringInfo) error { + return cs.System.AddGkr(gkr) } \ No newline at end of file diff --git a/internal/gkr/small_rational/gate_testing.go b/internal/gkr/small_rational/gate_testing.go index dc29624d7b..1817cfbf6f 100644 --- a/internal/gkr/small_rational/gate_testing.go +++ b/internal/gkr/small_rational/gate_testing.go @@ -146,7 +146,7 @@ func VerifyGateFunctionDegree(f gkr.GateFunction, claimedDegree, nbIn int) error // Note that the runtime is O(len(X)³) func interpolate(X, Y []small_rational.SmallRational) (polynomial.Polynomial, error) { if len(X) != len(Y) { - return nil, errors.New("X and Y must have the same length") + return nil, errors.New("same length expected for X and Y") } // solve the system of equations by Gaussian elimination diff --git a/internal/smallfields/tinyfield/element.go b/internal/smallfields/tinyfield/element.go index 67c17af924..67ecea6c7a 100644 --- a/internal/smallfields/tinyfield/element.go +++ b/internal/smallfields/tinyfield/element.go @@ -110,7 +110,7 @@ func (z *Element) Set(x *Element) *Element { } // SetInterface converts provided interface into Element -// returns an error if provided type is not supported +// returns an error if provided type is not supported. // supported types: // // Element @@ -834,19 +834,34 @@ func init() { // Legendre returns the Legendre symbol of z (either +1, -1, or 0.) func (z *Element) Legendre() int { - var l Element - // z^((q-1)/2) - l.Exp(*z, _bLegendreExponentElement) + // Use Binary GCD to compute the Legendre symbol. + a := z[0] + b := uint32(q0) + l := 1 // invariant: (z|q) = (a|b) . l + + for a != 0 { + pow2 := bits.TrailingZeros32(a) + a >>= pow2 + if bMod8 := b % 8; pow2%2 == 1 && (bMod8 == 3 || bMod8 == 5) { + l = -l // (2ⁿ|b) = 1 if b ≡ 1 or 7 (mod 8), and (-1)ⁿ if b ≡ 3 or 5 (mod 8) + } - if l.IsZero() { - return 0 + s, borrow := bits.Sub32(a, b, 0) + if borrow == 1 { + if b%4 == 3 && a%4 == 3 { + l = -l // (b-a|a) = (b|a). (b|a) = (a|b) unless a, b ≡ 3 (mod 4), in which case (b|a) = -(a|b). + } + a, b = b-a, a + } else { + a = s + } } - // if l == 1 - if l.IsOne() { - return 1 + if b == 1 { + return l // (0|1) = 1 + } else { + return 0 // if b ≠ 1, then (z,q) ≠ 0 ⇒ (z|q) = 0 } - return -1 } // Sqrt z = √x (mod q) diff --git a/internal/smallfields/tinyfield/element_test.go b/internal/smallfields/tinyfield/element_test.go index abf5055ba4..0d76ae1908 100644 --- a/internal/smallfields/tinyfield/element_test.go +++ b/internal/smallfields/tinyfield/element_test.go @@ -548,6 +548,7 @@ func TestElementLegendre(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) + require.Equal(t, 0, new(Element).Legendre(), "(0|q) must be zero") } func TestElementBitLen(t *testing.T) { diff --git a/internal/smallfields/tinyfield/vector.go b/internal/smallfields/tinyfield/vector.go index d062889879..2f63ec9294 100644 --- a/internal/smallfields/tinyfield/vector.go +++ b/internal/smallfields/tinyfield/vector.go @@ -73,7 +73,7 @@ func (vector *Vector) WriteTo(w io.Writer) (int64, error) { // It also returns a channel that will be closed when the validation is done. // The validation consist of checking that the elements are smaller than the modulus, and // converting them to montgomery form. -func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { +func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { // nolint ST1008 chErr := make(chan error, 1) var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { diff --git a/std/algebra/emulated/sw_bls12381/precomputations.go b/std/algebra/emulated/sw_bls12381/precomputations.go index 5049816f15..bd825c6a20 100644 --- a/std/algebra/emulated/sw_bls12381/precomputations.go +++ b/std/algebra/emulated/sw_bls12381/precomputations.go @@ -29,21 +29,21 @@ func precomputeLines(Q bls12381.G2Affine) lineEvaluations { return cLines } -func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations { +func (pr *Pairing) computeLines(Q *g2AffP) lineEvaluations { // check Q is on curve Qaff := G2Affine{P: *Q, Lines: nil} - p.IsOnTwist(&Qaff) + pr.IsOnTwist(&Qaff) var cLines lineEvaluations Qacc := Q n := len(loopCounter) - Qacc, cLines[0][n-2], cLines[1][n-2] = p.tripleStep(Qacc) + Qacc, cLines[0][n-2], cLines[1][n-2] = pr.tripleStep(Qacc) for i := n - 3; i >= 0; i-- { if loopCounter[i] == 0 { - Qacc, cLines[0][i] = p.doubleStep(Qacc) + Qacc, cLines[0][i] = pr.doubleStep(Qacc) } else { - Qacc, cLines[0][i], cLines[1][i] = p.doubleAndAddStep(Qacc, Q) + Qacc, cLines[0][i], cLines[1][i] = pr.doubleAndAddStep(Qacc, Q) } } @@ -52,8 +52,8 @@ func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations { // This test is equivalent to [AssertIsOnG2]. // // At this point Qacc = [x₀]Q. - psiQ := p.g2.psi(&Qaff) - p.g2.AssertIsEqual(p.g2.neg(&G2Affine{P: *Qacc, Lines: nil}), psiQ) + psiQ := pr.g2.psi(&Qaff) + pr.g2.AssertIsEqual(pr.g2.neg(&G2Affine{P: *Qacc, Lines: nil}), psiQ) return cLines } diff --git a/std/algebra/emulated/sw_bn254/precomputations.go b/std/algebra/emulated/sw_bn254/precomputations.go index 32bd85c773..ad01f60153 100644 --- a/std/algebra/emulated/sw_bn254/precomputations.go +++ b/std/algebra/emulated/sw_bn254/precomputations.go @@ -29,26 +29,26 @@ func precomputeLines(Q bn254.G2Affine) lineEvaluations { return cLines } -func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations { +func (pr *Pairing) computeLines(Q *g2AffP) lineEvaluations { // check Q is on curve Qaff := G2Affine{P: *Q, Lines: nil} - p.IsOnTwist(&Qaff) + pr.IsOnTwist(&Qaff) var cLines lineEvaluations Qacc := Q n := len(bn254.LoopCounter) - Qacc, cLines[0][n-2] = p.doubleStep(Qacc) - cLines[1][n-3] = p.lineCompute(Qacc, Q) - Qacc, cLines[0][n-3] = p.addStep(Qacc, Q) + Qacc, cLines[0][n-2] = pr.doubleStep(Qacc) + cLines[1][n-3] = pr.lineCompute(Qacc, Q) + Qacc, cLines[0][n-3] = pr.addStep(Qacc, Q) for i := n - 4; i >= 0; i-- { switch loopCounter[i] { case 0: - Qacc, cLines[0][i] = p.doubleStep(Qacc) + Qacc, cLines[0][i] = pr.doubleStep(Qacc) case 1: - Qacc, cLines[0][i], cLines[1][i] = p.doubleAndAddStep(Qacc, Q, false) + Qacc, cLines[0][i], cLines[1][i] = pr.doubleAndAddStep(Qacc, Q, false) case -1: - Qacc, cLines[0][i], cLines[1][i] = p.doubleAndAddStep(Qacc, Q, true) + Qacc, cLines[0][i], cLines[1][i] = pr.doubleAndAddStep(Qacc, Q, true) default: return lineEvaluations{} } @@ -61,30 +61,30 @@ func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations { // This test is equivalent to [computeG2ShortVector] in [AssertIsOnG2]. // // At this point Qacc = [6x₀+2]Q. - psiQ := p.g2.psi(&Qaff) // ψ(Q) - psi2Q := p.g2.phi(&Qaff) // ϕ(Q)=ψ²(Q) - psi3Q := p.g2.psi(psi2Q) // ψ³(Q) - lhs := p.g2.add(&G2Affine{P: *Qacc, Lines: nil}, psiQ) - lhs = p.g2.add(lhs, psi3Q) - p.g2.AssertIsEqual(lhs, psi2Q) + psiQ := pr.g2.psi(&Qaff) // ψ(Q) + psi2Q := pr.g2.phi(&Qaff) // ϕ(Q)=ψ²(Q) + psi3Q := pr.g2.psi(psi2Q) // ψ³(Q) + lhs := pr.g2.add(&G2Affine{P: *Qacc, Lines: nil}, psiQ) + lhs = pr.g2.add(lhs, psi3Q) + pr.g2.AssertIsEqual(lhs, psi2Q) - Q1X := p.Ext2.Conjugate(&Q.X) - Q1X = p.Ext2.MulByNonResidue1Power2(Q1X) - Q1Y := p.Ext2.Conjugate(&Q.Y) - Q1Y = p.Ext2.MulByNonResidue1Power3(Q1Y) + Q1X := pr.Ext2.Conjugate(&Q.X) + Q1X = pr.Ext2.MulByNonResidue1Power2(Q1X) + Q1Y := pr.Ext2.Conjugate(&Q.Y) + Q1Y = pr.Ext2.MulByNonResidue1Power3(Q1Y) Q1 := &g2AffP{ X: *Q1X, Y: *Q1Y, } - Q2Y := p.Ext2.MulByNonResidue2Power3(&Q.Y) + Q2Y := pr.Ext2.MulByNonResidue2Power3(&Q.Y) Q2 := &g2AffP{ - X: *p.Ext2.MulByNonResidue2Power2(&Q.X), + X: *pr.Ext2.MulByNonResidue2Power2(&Q.X), Y: *Q2Y, } - Qacc, cLines[0][n-1] = p.addStep(Qacc, Q1) - cLines[1][n-1] = p.lineCompute(Qacc, Q2) + Qacc, cLines[0][n-1] = pr.addStep(Qacc, Q1) + cLines[1][n-1] = pr.lineCompute(Qacc, Q2) return cLines } diff --git a/std/algebra/emulated/sw_bw6761/precomputations.go b/std/algebra/emulated/sw_bw6761/precomputations.go index 24ff7a49fe..b6ff8ce322 100644 --- a/std/algebra/emulated/sw_bw6761/precomputations.go +++ b/std/algebra/emulated/sw_bw6761/precomputations.go @@ -29,11 +29,11 @@ func precomputeLines(Q bw6761.G2Affine) lineEvaluations { return cLines } -func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations { +func (pr *Pairing) computeLines(Q *g2AffP) lineEvaluations { var cLines lineEvaluations imQ := &g2AffP{ - X: *p.curveF.Mul(&Q.X, p.thirdRootOne), - Y: *p.curveF.Neg(&Q.Y), + X: *pr.curveF.Mul(&Q.X, pr.thirdRootOne), + Y: *pr.curveF.Neg(&Q.Y), } accQ := &g2AffP{ X: imQ.X, @@ -43,15 +43,15 @@ func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations { switch loopCounter2[i]*3 + loopCounter1[i] { // cases -4, -2, 2, 4 do not occur, given the static LoopCounters case -3: - accQ, cLines[0][i], cLines[1][i] = p.doubleAndAddStep(accQ, imQ, true) + accQ, cLines[0][i], cLines[1][i] = pr.doubleAndAddStep(accQ, imQ, true) case -1: - accQ, cLines[0][i], cLines[1][i] = p.doubleAndAddStep(accQ, Q, true) + accQ, cLines[0][i], cLines[1][i] = pr.doubleAndAddStep(accQ, Q, true) case 0: - accQ, cLines[0][i] = p.doubleStep(accQ) + accQ, cLines[0][i] = pr.doubleStep(accQ) case 1: - accQ, cLines[0][i], cLines[1][i] = p.doubleAndAddStep(accQ, Q, false) + accQ, cLines[0][i], cLines[1][i] = pr.doubleAndAddStep(accQ, Q, false) case 3: - accQ, cLines[0][i], cLines[1][i] = p.doubleAndAddStep(accQ, imQ, false) + accQ, cLines[0][i], cLines[1][i] = pr.doubleAndAddStep(accQ, imQ, false) default: panic("unknown case for loopCounter") } @@ -59,6 +59,6 @@ func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations { // i = 0 (case -3) // x₀+1+λ(x₀³-x₀²-x₀) = 0 mod r so accQ = ∞ at the last iteration, // we only compute the tangent. - cLines[0][0] = p.tangentCompute(accQ) + cLines[0][0] = pr.tangentCompute(accQ) return cLines } diff --git a/std/algebra/emulated/sw_emulated/hints.go b/std/algebra/emulated/sw_emulated/hints.go index 58cd868776..eda429b9fb 100644 --- a/std/algebra/emulated/sw_emulated/hints.go +++ b/std/algebra/emulated/sw_emulated/hints.go @@ -212,24 +212,24 @@ func halfGCDEisenstein(mod *big.Int, inputs []*big.Int, outputs []*big.Int) erro glvBasis := new(ecc.Lattice) ecc.PrecomputeLattice(moduli[0], emuInputs[1], glvBasis) r := eisenstein.ComplexNumber{ - A0: &glvBasis.V1[0], - A1: &glvBasis.V1[1], + A0: glvBasis.V1[0], + A1: glvBasis.V1[1], } sp := ecc.SplitScalar(emuInputs[0], glvBasis) // in-circuit we check that Q - [s]P = 0 or equivalently Q + [-s]P = 0 // so here we return -s instead of s. s := eisenstein.ComplexNumber{ - A0: &sp[0], - A1: &sp[1], + A0: sp[0], + A1: sp[1], } s.Neg(&s) res := eisenstein.HalfGCD(&r, &s) // values - emuOutputs[0].Set(res[0].A0) - emuOutputs[1].Set(res[0].A1) - emuOutputs[2].Set(res[1].A0) - emuOutputs[3].Set(res[1].A1) + emuOutputs[0].Set(&res[0].A0) + emuOutputs[1].Set(&res[0].A1) + emuOutputs[2].Set(&res[1].A0) + emuOutputs[3].Set(&res[1].A1) // signs nativeOutputs[0].SetUint64(0) nativeOutputs[1].SetUint64(0) diff --git a/std/algebra/native/fields_bls12377/e12_pairing.go b/std/algebra/native/fields_bls12377/e12_pairing.go index f1715e4806..cc80e24ff8 100644 --- a/std/algebra/native/fields_bls12377/e12_pairing.go +++ b/std/algebra/native/fields_bls12377/e12_pairing.go @@ -212,8 +212,8 @@ func (e *E12) ExpU(api frontend.API, e1 E12) *E12 { // The method follows Section 4 of [On Proving Pairings] paper by A. Novakovic and L. Eagen. // // [On Proving Pairings]: https://eprint.iacr.org/2024/640.pdf -func (x *E12) AssertFinalExponentiationIsOne(api frontend.API) { - res, err := api.NewHint(finalExpHint, 18, x.C0.B0.A0, x.C0.B0.A1, x.C0.B1.A0, x.C0.B1.A1, x.C0.B2.A0, x.C0.B2.A1, x.C1.B0.A0, x.C1.B0.A1, x.C1.B1.A0, x.C1.B1.A1, x.C1.B2.A0, x.C1.B2.A1) +func (e *E12) AssertFinalExponentiationIsOne(api frontend.API) { + res, err := api.NewHint(finalExpHint, 18, e.C0.B0.A0, e.C0.B0.A1, e.C0.B1.A0, e.C0.B1.A1, e.C0.B2.A0, e.C0.B2.A1, e.C1.B0.A0, e.C1.B0.A1, e.C1.B1.A0, e.C1.B1.A1, e.C1.B2.A0, e.C1.B2.A1) if err != nil { // err is non-nil only for invalid number of inputs panic(err) @@ -238,8 +238,8 @@ func (x *E12) AssertFinalExponentiationIsOne(api frontend.API) { t1.ExpX0(api, residueWitness) t0.DivUnchecked(api, t0, t1) - t1.C0.Mul(api, x.C0, scalingFactor) - t1.C1.Mul(api, x.C1, scalingFactor) + t1.C0.Mul(api, e.C0, scalingFactor) + t1.C1.Mul(api, e.C1, scalingFactor) t0.AssertIsEqual(api, t1) } diff --git a/std/algebra/native/sw_bls12377/g1.go b/std/algebra/native/sw_bls12377/g1.go index 0bd8c8e2db..fd39f94074 100644 --- a/std/algebra/native/sw_bls12377/g1.go +++ b/std/algebra/native/sw_bls12377/g1.go @@ -134,7 +134,7 @@ func (p *G1Affine) Double(api frontend.API, p1 G1Affine) *G1Affine { return p } -func (P *G1Affine) doubleN(api frontend.API, Q *G1Affine, n int) *G1Affine { +func (p *G1Affine) doubleN(api frontend.API, Q *G1Affine, n int) *G1Affine { pn := Q for s := 0; s < n; s++ { pn.Double(api, *pn) @@ -142,7 +142,7 @@ func (P *G1Affine) doubleN(api frontend.API, Q *G1Affine, n int) *G1Affine { return pn } -func (P *G1Affine) scalarMulBySeed(api frontend.API, Q *G1Affine) *G1Affine { +func (p *G1Affine) scalarMulBySeed(api frontend.API, Q *G1Affine) *G1Affine { var z, t0, t1 G1Affine z.Double(api, *Q) z.AddAssign(api, *Q) @@ -156,9 +156,9 @@ func (P *G1Affine) scalarMulBySeed(api frontend.API, Q *G1Affine) *G1Affine { t0.doubleN(api, &t0, 9) z.DoubleAndAdd(api, &t0, &z) z.doubleN(api, &z, 45) - P.DoubleAndAdd(api, &z, Q) + p.DoubleAndAdd(api, &z, Q) - return P + return p } // ScalarMul sets P = [s] Q and returns P. @@ -166,11 +166,11 @@ func (P *G1Affine) scalarMulBySeed(api frontend.API, Q *G1Affine) *G1Affine { // The method chooses an implementation based on scalar s. If it is constant, // then the compiled circuit depends on s. If it is variable type, then // the circuit is independent of the inputs. -func (P *G1Affine) ScalarMul(api frontend.API, Q G1Affine, s interface{}, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) ScalarMul(api frontend.API, Q G1Affine, s interface{}, opts ...algopts.AlgebraOption) *G1Affine { if n, ok := api.Compiler().ConstantValue(s); ok { - return P.constScalarMul(api, Q, n, opts...) + return p.constScalarMul(api, Q, n, opts...) } else { - return P.varScalarMul(api, Q, s, opts...) + return p.varScalarMul(api, Q, s, opts...) } } @@ -183,7 +183,7 @@ func (P *G1Affine) ScalarMul(api frontend.API, Q G1Affine, s interface{}, opts . // // [Halo]: https://eprint.iacr.org/2019/1021.pdf // [EVM]: https://ethereum.github.io/yellowpaper/paper.pdf -func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) @@ -301,22 +301,22 @@ func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variabl Acc.AddAssign(api, G1Affine{X: 0, Y: -1}) } - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } // constScalarMul sets P = [s] Q and returns P. -func (P *G1Affine) constScalarMul(api frontend.API, Q G1Affine, s *big.Int, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) constScalarMul(api frontend.API, Q G1Affine, s *big.Int, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) } if s.BitLen() == 0 { - P.X = 0 - P.Y = 0 - return P + p.X = 0 + p.Y = 0 + return p } // see the comments in varScalarMul. However, two-bit lookup is cheaper if // bits are constant and here it makes sense to use the table in the main @@ -392,9 +392,9 @@ func (P *G1Affine) constScalarMul(api frontend.API, Q G1Affine, s *big.Int, opts negPhiQ.AddAssign(api, Acc) } Acc.Select(api, k[1].Bit(0), Acc, negPhiQ) - P.X, P.Y = Acc.X, Acc.Y + p.X, p.Y = Acc.X, Acc.Y - return P + return p } // Assign a value to self (witness assignment) @@ -440,33 +440,33 @@ func (p *G1Affine) DoubleAndAdd(api frontend.API, p1, p2 *G1Affine) *G1Affine { } // ScalarMulBase computes s * g1 and returns it, where g1 is the fixed generator. It doesn't modify s. -func (P *G1Affine) ScalarMulBase(api frontend.API, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) ScalarMulBase(api frontend.API, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { _, _, g1aff, _ := bls12377.Generators() generator := G1Affine{ X: g1aff.X.BigInt(new(big.Int)), Y: g1aff.Y.BigInt(new(big.Int)), } - return P.ScalarMul(api, generator, s, opts...) + return p.ScalarMul(api, generator, s, opts...) } -func (P *G1Affine) jointScalarMul(api frontend.API, Q, R G1Affine, s, t frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) jointScalarMul(api frontend.API, Q, R G1Affine, s, t frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) } if cfg.CompleteArithmetic { var tmp G1Affine - P.ScalarMul(api, Q, s, opts...) + p.ScalarMul(api, Q, s, opts...) tmp.ScalarMul(api, R, t, opts...) - P.AddUnified(api, tmp) + p.AddUnified(api, tmp) } else { - P.jointScalarMulUnsafe(api, Q, R, s, t) + p.jointScalarMulUnsafe(api, Q, R, s, t) } - return P + return p } // P = [s]Q + [t]R using Shamir's trick -func (P *G1Affine) jointScalarMulUnsafe(api frontend.API, Q, R G1Affine, s, t frontend.Variable) *G1Affine { +func (p *G1Affine) jointScalarMulUnsafe(api frontend.API, Q, R G1Affine, s, t frontend.Variable) *G1Affine { cc := getInnerCurveConfig(api.Compiler().Field()) sd, err := api.Compiler().NewHint(decomposeScalarG1Simple, 2, s) @@ -545,15 +545,15 @@ func (P *G1Affine) jointScalarMulUnsafe(api frontend.API, Q, R G1Affine, s, t fr tablePhiR[0].AddAssign(api, Acc) Acc.Select(api, t2bits[0], Acc, tablePhiR[0]) - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } // scalarBitsMul computes [s]Q and returns it where sBits is the bit decomposition of s. It doesn't modify Q nor sBits. // The method is similar to varScalarMul. -func (P *G1Affine) scalarBitsMul(api frontend.API, Q G1Affine, s1bits, s2bits []frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) scalarBitsMul(api frontend.API, Q G1Affine, s1bits, s2bits []frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) @@ -654,16 +654,16 @@ func (P *G1Affine) scalarBitsMul(api frontend.API, Q G1Affine, s1bits, s2bits [] } - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } // fake-GLV // // N.B.: this method is more expensive than classical GLV, but it is useful for testing purposes. -func (R *G1Affine) scalarMulGLVAndFakeGLV(api frontend.API, P G1Affine, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) scalarMulGLVAndFakeGLV(api frontend.API, P G1Affine, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) @@ -859,8 +859,8 @@ func (R *G1Affine) scalarMulGLVAndFakeGLV(api frontend.API, P G1Affine, s fronte } Acc.AssertIsEqual(api, H) - R.X = point[0] - R.Y = point[1] + p.X = point[0] + p.Y = point[1] - return R + return p } diff --git a/std/algebra/native/sw_bls12377/g2.go b/std/algebra/native/sw_bls12377/g2.go index b21b57453e..440e30242f 100644 --- a/std/algebra/native/sw_bls12377/g2.go +++ b/std/algebra/native/sw_bls12377/g2.go @@ -141,7 +141,7 @@ func (p *g2AffP) Double(api frontend.API, p1 g2AffP) *g2AffP { } -func (P *g2AffP) doubleN(api frontend.API, Q *g2AffP, n int) *g2AffP { +func (p *g2AffP) doubleN(api frontend.API, Q *g2AffP, n int) *g2AffP { pn := Q for s := 0; s < n; s++ { pn.Double(api, *pn) @@ -149,7 +149,7 @@ func (P *g2AffP) doubleN(api frontend.API, Q *g2AffP, n int) *g2AffP { return pn } -func (P *g2AffP) scalarMulBySeed(api frontend.API, Q *g2AffP) *g2AffP { +func (p *g2AffP) scalarMulBySeed(api frontend.API, Q *g2AffP) *g2AffP { var z, t0, t1 g2AffP z.Double(api, *Q) z.AddAssign(api, *Q) @@ -163,9 +163,9 @@ func (P *g2AffP) scalarMulBySeed(api frontend.API, Q *g2AffP) *g2AffP { t0.doubleN(api, &t0, 9) z.DoubleAndAdd(api, &t0, &z) z.doubleN(api, &z, 45) - P.DoubleAndAdd(api, &z, Q) + p.DoubleAndAdd(api, &z, Q) - return P + return p } // ScalarMul sets P = [s] Q and returns P. @@ -173,11 +173,11 @@ func (P *g2AffP) scalarMulBySeed(api frontend.API, Q *g2AffP) *g2AffP { // The method chooses an implementation based on scalar s. If it is constant, // then the compiled circuit depends on s. If it is variable type, then // the circuit is independent of the inputs. -func (P *g2AffP) ScalarMul(api frontend.API, Q g2AffP, s interface{}, opts ...algopts.AlgebraOption) *g2AffP { +func (p *g2AffP) ScalarMul(api frontend.API, Q g2AffP, s interface{}, opts ...algopts.AlgebraOption) *g2AffP { if n, ok := api.Compiler().ConstantValue(s); ok { - return P.constScalarMul(api, Q, n, opts...) + return p.constScalarMul(api, Q, n, opts...) } else { - return P.varScalarMul(api, Q, s, opts...) + return p.varScalarMul(api, Q, s, opts...) } } @@ -190,7 +190,7 @@ func (P *g2AffP) ScalarMul(api frontend.API, Q g2AffP, s interface{}, opts ...al // // [Halo]: https://eprint.iacr.org/2019/1021.pdf // [EVM]: https://ethereum.github.io/yellowpaper/paper.pdf -func (P *g2AffP) varScalarMul(api frontend.API, Q g2AffP, s frontend.Variable, opts ...algopts.AlgebraOption) *g2AffP { +func (p *g2AffP) varScalarMul(api frontend.API, Q g2AffP, s frontend.Variable, opts ...algopts.AlgebraOption) *g2AffP { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) @@ -323,23 +323,23 @@ func (P *g2AffP) varScalarMul(api frontend.API, Q g2AffP, s frontend.Variable, o Acc.Select(api, selector, g2AffP{X: zero, Y: zero}, Acc) } - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } // constScalarMul sets P = [s] Q and returns P. -func (P *g2AffP) constScalarMul(api frontend.API, Q g2AffP, s *big.Int, opts ...algopts.AlgebraOption) *g2AffP { +func (p *g2AffP) constScalarMul(api frontend.API, Q g2AffP, s *big.Int, opts ...algopts.AlgebraOption) *g2AffP { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) } if s.BitLen() == 0 { zero := fields_bls12377.E2{A0: 0, A1: 0} - P.X = zero - P.Y = zero - return P + p.X = zero + p.Y = zero + return p } // see the comments in varScalarMul. However, two-bit lookup is cheaper if // bits are constant and here it makes sense to use the table in the main @@ -415,9 +415,9 @@ func (P *g2AffP) constScalarMul(api frontend.API, Q g2AffP, s *big.Int, opts ... negPhiQ.AddAssign(api, Acc) } Acc.Select(api, k[1].Bit(0), Acc, negPhiQ) - P.X, P.Y = Acc.X, Acc.Y + p.X, p.Y = Acc.X, Acc.Y - return P + return p } // Assign a value to self (witness assignment) @@ -471,7 +471,7 @@ func (p *g2AffP) DoubleAndAdd(api frontend.API, p1, p2 *g2AffP) *g2AffP { } // ScalarMulBase computes s * g2 and returns it, where g2 is the fixed generator. It doesn't modify s. -func (P *g2AffP) ScalarMulBase(api frontend.API, s frontend.Variable) *g2AffP { +func (p *g2AffP) ScalarMulBase(api frontend.API, s frontend.Variable) *g2AffP { points := getTwistPoints() @@ -529,21 +529,21 @@ func (P *g2AffP) ScalarMulBase(api frontend.API, s frontend.Variable) *g2AffP { tmp.AddAssign(api, res) res.Select(api, sBits[0], res, tmp) - P.X = res.X - P.Y = res.Y + p.X = res.X + p.Y = res.Y - return P + return p } -func (P *g2AffP) psi(api frontend.API, q *g2AffP) *g2AffP { +func (p *g2AffP) psi(api frontend.API, q *g2AffP) *g2AffP { var x, y fields_bls12377.E2 x.Conjugate(api, q.X) x.MulByFp(api, x, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946") y.Conjugate(api, q.Y) y.MulByFp(api, y, "216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499") - P.X = x - P.Y = y + p.X = x + p.Y = y - return P + return p } diff --git a/std/algebra/native/sw_bls12377/hints.go b/std/algebra/native/sw_bls12377/hints.go index c9685a7671..5aa1b7523d 100644 --- a/std/algebra/native/sw_bls12377/hints.go +++ b/std/algebra/native/sw_bls12377/hints.go @@ -207,31 +207,31 @@ func halfGCDEisenstein(scalarField *big.Int, inputs []*big.Int, outputs []*big.I glvBasis := new(ecc.Lattice) ecc.PrecomputeLattice(cc.fr, inputs[1], glvBasis) r := eisenstein.ComplexNumber{ - A0: &glvBasis.V1[0], - A1: &glvBasis.V1[1], + A0: glvBasis.V1[0], + A1: glvBasis.V1[1], } sp := ecc.SplitScalar(inputs[0], glvBasis) // in-circuit we check that Q - [s]P = 0 or equivalently Q + [-s]P = 0 // so here we return -s instead of s. s := eisenstein.ComplexNumber{ - A0: &sp[0], - A1: &sp[1], + A0: sp[0], + A1: sp[1], } s.Neg(&s) res := eisenstein.HalfGCD(&r, &s) - outputs[0].Set(res[0].A0) - outputs[1].Set(res[0].A1) - outputs[2].Set(res[1].A0) - outputs[3].Set(res[1].A1) - outputs[4].Mul(res[1].A1, inputs[1]). - Add(outputs[4], res[1].A0). + outputs[0].Set(&res[0].A0) + outputs[1].Set(&res[0].A1) + outputs[2].Set(&res[1].A0) + outputs[3].Set(&res[1].A1) + outputs[4].Mul(&res[1].A1, inputs[1]). + Add(outputs[4], &res[1].A0). Mul(outputs[4], inputs[0]). - Add(outputs[4], res[0].A0) - s.A0.Mul(res[0].A1, inputs[1]) - outputs[4].Add(outputs[4], s.A0). + Add(outputs[4], &res[0].A0) + s.A0.Mul(&res[0].A1, inputs[1]) + outputs[4].Add(outputs[4], &s.A0). Div(outputs[4], cc.fr) - // set the signs + // set the signs outputs[5].SetUint64(0) outputs[6].SetUint64(0) outputs[7].SetUint64(0) diff --git a/std/algebra/native/sw_bls12377/pairing2.go b/std/algebra/native/sw_bls12377/pairing2.go index 50f2366dca..dea53cc1e7 100644 --- a/std/algebra/native/sw_bls12377/pairing2.go +++ b/std/algebra/native/sw_bls12377/pairing2.go @@ -106,39 +106,39 @@ func (c *Curve) AssertIsEqual(P, Q *G1Affine) { P.AssertIsEqual(c.api, *Q) } -func (c *Pairing) IsEqual(x, y *GT) frontend.Variable { - diff0 := c.api.Sub(&x.C0.B0.A0, &y.C0.B0.A0) - diff1 := c.api.Sub(&x.C0.B0.A1, &y.C0.B0.A1) - diff2 := c.api.Sub(&x.C0.B0.A0, &y.C0.B0.A0) - diff3 := c.api.Sub(&x.C0.B1.A1, &y.C0.B1.A1) - diff4 := c.api.Sub(&x.C0.B1.A0, &y.C0.B1.A0) - diff5 := c.api.Sub(&x.C0.B1.A1, &y.C0.B1.A1) - diff6 := c.api.Sub(&x.C1.B0.A0, &y.C1.B0.A0) - diff7 := c.api.Sub(&x.C1.B0.A1, &y.C1.B0.A1) - diff8 := c.api.Sub(&x.C1.B0.A0, &y.C1.B0.A0) - diff9 := c.api.Sub(&x.C1.B1.A1, &y.C1.B1.A1) - diff10 := c.api.Sub(&x.C1.B1.A0, &y.C1.B1.A0) - diff11 := c.api.Sub(&x.C1.B1.A1, &y.C1.B1.A1) - - isZero0 := c.api.IsZero(diff0) - isZero1 := c.api.IsZero(diff1) - isZero2 := c.api.IsZero(diff2) - isZero3 := c.api.IsZero(diff3) - isZero4 := c.api.IsZero(diff4) - isZero5 := c.api.IsZero(diff5) - isZero6 := c.api.IsZero(diff6) - isZero7 := c.api.IsZero(diff7) - isZero8 := c.api.IsZero(diff8) - isZero9 := c.api.IsZero(diff9) - isZero10 := c.api.IsZero(diff10) - isZero11 := c.api.IsZero(diff11) - - return c.api.And( - c.api.And( - c.api.And(c.api.And(isZero0, isZero1), c.api.And(isZero2, isZero3)), - c.api.And(c.api.And(isZero4, isZero5), c.api.And(isZero6, isZero7)), +func (pr *Pairing) IsEqual(x, y *GT) frontend.Variable { + diff0 := pr.api.Sub(&x.C0.B0.A0, &y.C0.B0.A0) + diff1 := pr.api.Sub(&x.C0.B0.A1, &y.C0.B0.A1) + diff2 := pr.api.Sub(&x.C0.B0.A0, &y.C0.B0.A0) + diff3 := pr.api.Sub(&x.C0.B1.A1, &y.C0.B1.A1) + diff4 := pr.api.Sub(&x.C0.B1.A0, &y.C0.B1.A0) + diff5 := pr.api.Sub(&x.C0.B1.A1, &y.C0.B1.A1) + diff6 := pr.api.Sub(&x.C1.B0.A0, &y.C1.B0.A0) + diff7 := pr.api.Sub(&x.C1.B0.A1, &y.C1.B0.A1) + diff8 := pr.api.Sub(&x.C1.B0.A0, &y.C1.B0.A0) + diff9 := pr.api.Sub(&x.C1.B1.A1, &y.C1.B1.A1) + diff10 := pr.api.Sub(&x.C1.B1.A0, &y.C1.B1.A0) + diff11 := pr.api.Sub(&x.C1.B1.A1, &y.C1.B1.A1) + + isZero0 := pr.api.IsZero(diff0) + isZero1 := pr.api.IsZero(diff1) + isZero2 := pr.api.IsZero(diff2) + isZero3 := pr.api.IsZero(diff3) + isZero4 := pr.api.IsZero(diff4) + isZero5 := pr.api.IsZero(diff5) + isZero6 := pr.api.IsZero(diff6) + isZero7 := pr.api.IsZero(diff7) + isZero8 := pr.api.IsZero(diff8) + isZero9 := pr.api.IsZero(diff9) + isZero10 := pr.api.IsZero(diff10) + isZero11 := pr.api.IsZero(diff11) + + return pr.api.And( + pr.api.And( + pr.api.And(pr.api.And(isZero0, isZero1), pr.api.And(isZero2, isZero3)), + pr.api.And(pr.api.And(isZero4, isZero5), pr.api.And(isZero6, isZero7)), ), - c.api.And(c.api.And(isZero8, isZero9), c.api.And(isZero10, isZero11)), + pr.api.And(pr.api.And(isZero8, isZero9), pr.api.And(isZero10, isZero11)), ) } @@ -303,7 +303,7 @@ func NewPairing(api frontend.API) *Pairing { // MillerLoop computes the Miller loop between the pairs of inputs. It doesn't // modify the inputs. It returns an error if there is a mismatch between the // lengths of the inputs. -func (p *Pairing) MillerLoop(P []*G1Affine, Q []*G2Affine) (*GT, error) { +func (pr *Pairing) MillerLoop(P []*G1Affine, Q []*G2Affine) (*GT, error) { inP := make([]G1Affine, len(P)) for i := range P { inP[i] = *P[i] @@ -312,19 +312,19 @@ func (p *Pairing) MillerLoop(P []*G1Affine, Q []*G2Affine) (*GT, error) { for i := range Q { inQ[i] = *Q[i] } - res, err := MillerLoop(p.api, inP, inQ) + res, err := MillerLoop(pr.api, inP, inQ) return &res, err } // FinalExponentiation performs the final exponentiation on the target group // element. It doesn't modify the input. -func (p *Pairing) FinalExponentiation(e *GT) *GT { - res := FinalExponentiation(p.api, *e) +func (pr *Pairing) FinalExponentiation(e *GT) *GT { + res := FinalExponentiation(pr.api, *e) return &res } // Pair computes a full multi-pairing on the input pairs. -func (p *Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GT, error) { +func (pr *Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GT, error) { inP := make([]G1Affine, len(P)) for i := range P { inP[i] = *P[i] @@ -333,14 +333,14 @@ func (p *Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GT, error) { for i := range Q { inQ[i] = *Q[i] } - res, err := Pair(p.api, inP, inQ) + res, err := Pair(pr.api, inP, inQ) return &res, err } // PairingCheck computes the multi-pairing of the input pairs and asserts that // the result is an identity element in the target group. It returns an error if // there is a mismatch between the lengths of the inputs. -func (p *Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { +func (pr *Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { inP := make([]G1Affine, len(P)) for i := range P { inP[i] = *P[i] @@ -349,7 +349,7 @@ func (p *Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { for i := range Q { inQ[i] = *Q[i] } - err := PairingCheck(p.api, inP, inQ) + err := PairingCheck(pr.api, inP, inQ) if err != nil { return err } @@ -358,8 +358,8 @@ func (p *Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { } // AssertIsEqual asserts the equality of the target group elements. -func (p *Pairing) AssertIsEqual(e1, e2 *GT) { - e1.AssertIsEqual(p.api, *e2) +func (pr *Pairing) AssertIsEqual(e1, e2 *GT) { + e1.AssertIsEqual(pr.api, *e2) } func (pr Pairing) MuxG2(sel frontend.Variable, inputs ...*G2Affine) *G2Affine { @@ -477,73 +477,73 @@ func (pr Pairing) MuxGt(sel frontend.Variable, inputs ...*GT) *GT { } // AssertIsOnCurve asserts if p belongs to the curve. It doesn't modify p. -func (c *Pairing) AssertIsOnCurve(p *G1Affine) { +func (pr *Pairing) AssertIsOnCurve(p *G1Affine) { // (X,Y) ∈ {Y² == X³ + 1} U (0,0) // if p=(0,0) we assign b=0 and continue - selector := c.api.And(c.api.IsZero(p.X), c.api.IsZero(p.Y)) - b := c.api.Select(selector, 0, 1) + selector := pr.api.And(pr.api.IsZero(p.X), pr.api.IsZero(p.Y)) + b := pr.api.Select(selector, 0, 1) - left := c.api.Mul(p.Y, p.Y) - right := c.api.Mul(p.X, c.api.Mul(p.X, p.X)) - right = c.api.Add(right, b) - c.api.AssertIsEqual(left, right) + left := pr.api.Mul(p.Y, p.Y) + right := pr.api.Mul(p.X, pr.api.Mul(p.X, p.X)) + right = pr.api.Add(right, b) + pr.api.AssertIsEqual(left, right) } -func (c *Pairing) AssertIsOnG1(P *G1Affine) { +func (pr *Pairing) AssertIsOnG1(P *G1Affine) { // 1- Check P is on the curve - c.AssertIsOnCurve(P) + pr.AssertIsOnCurve(P) // 2- Check P has the right subgroup order // [x²]ϕ(P) phiP := G1Affine{ - X: c.api.Mul(P.X, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"), + X: pr.api.Mul(P.X, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"), Y: P.Y, } var _P G1Affine - _P.scalarMulBySeed(c.api, &phiP) - _P.scalarMulBySeed(c.api, &_P) - _P.Neg(c.api, _P) + _P.scalarMulBySeed(pr.api, &phiP) + _P.scalarMulBySeed(pr.api, &_P) + _P.Neg(pr.api, _P) // [r]Q == 0 <==> P = -[x²]ϕ(P) - P.AssertIsEqual(c.api, _P) + P.AssertIsEqual(pr.api, _P) } // AssertIsOnTwist asserts if p belongs to the curve. It doesn't modify p. -func (c *Pairing) AssertIsOnTwist(p *G2Affine) { +func (pr *Pairing) AssertIsOnTwist(p *G2Affine) { // (X,Y) ∈ {Y² == X³ + 1/u} U (0,0) // if p=(0,0) we assign b=0 and continue - selector := c.api.And(p.P.X.IsZero(c.api), p.P.Y.IsZero(c.api)) + selector := pr.api.And(p.P.X.IsZero(pr.api), p.P.Y.IsZero(pr.api)) var zero fields_bls12377.E2 zero.SetZero() b := fields_bls12377.E2{ A0: 0, A1: "155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906", } - b.Select(c.api, selector, zero, b) + b.Select(pr.api, selector, zero, b) var left, right fields_bls12377.E2 - left.Square(c.api, p.P.Y) - right.Square(c.api, p.P.X) - right.Mul(c.api, right, p.P.X) - right.Add(c.api, right, b) - left.AssertIsEqual(c.api, right) + left.Square(pr.api, p.P.Y) + right.Square(pr.api, p.P.X) + right.Mul(pr.api, right, p.P.X) + right.Add(pr.api, right, b) + left.AssertIsEqual(pr.api, right) } -func (c *Pairing) AssertIsOnG2(P *G2Affine) { +func (pr *Pairing) AssertIsOnG2(P *G2Affine) { // 1- Check P is on the curve - c.AssertIsOnTwist(P) + pr.AssertIsOnTwist(P) // 2- Check P has the right subgroup order // [x₀]Q var xP, psiP g2AffP - xP.scalarMulBySeed(c.api, &P.P) + xP.scalarMulBySeed(pr.api, &P.P) // ψ(Q) - psiP.psi(c.api, &P.P) + psiP.psi(pr.api, &P.P) // [r]Q == 0 <==> ψ(Q) == [x₀]Q - xP.AssertIsEqual(c.api, psiP) + xP.AssertIsEqual(pr.api, psiP) } // NewG1Affine allocates a witness from the native G1 element and returns it. diff --git a/std/algebra/native/sw_bls24315/g1.go b/std/algebra/native/sw_bls24315/g1.go index 9774006f1b..74d6a7e547 100644 --- a/std/algebra/native/sw_bls24315/g1.go +++ b/std/algebra/native/sw_bls24315/g1.go @@ -137,11 +137,11 @@ func (p *G1Affine) Double(api frontend.API, p1 G1Affine) *G1Affine { // The method chooses an implementation based on scalar s. If it is constant, // then the compiled circuit depends on s. If it is variable type, then // the circuit is independent of the inputs. -func (P *G1Affine) ScalarMul(api frontend.API, Q G1Affine, s interface{}, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) ScalarMul(api frontend.API, Q G1Affine, s interface{}, opts ...algopts.AlgebraOption) *G1Affine { if n, ok := api.Compiler().ConstantValue(s); ok { - return P.constScalarMul(api, Q, n, opts...) + return p.constScalarMul(api, Q, n, opts...) } else { - return P.varScalarMul(api, Q, s, opts...) + return p.varScalarMul(api, Q, s, opts...) } } @@ -154,7 +154,7 @@ func (P *G1Affine) ScalarMul(api frontend.API, Q G1Affine, s interface{}, opts . // // [Halo]: https://eprint.iacr.org/2019/1021.pdf // [EVM]: https://ethereum.github.io/yellowpaper/paper.pdf -func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) @@ -257,22 +257,22 @@ func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variabl Acc.AddAssign(api, G1Affine{X: 0, Y: -1}) } - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } // constScalarMul sets P = [s] Q and returns P. -func (P *G1Affine) constScalarMul(api frontend.API, Q G1Affine, s *big.Int, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) constScalarMul(api frontend.API, Q G1Affine, s *big.Int, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) } if s.BitLen() == 0 { - P.X = 0 - P.Y = 0 - return P + p.X = 0 + p.Y = 0 + return p } // see the comments in varScalarMul. However, two-bit lookup is cheaper if // bits are constant and here it makes sense to use the table in the main @@ -348,9 +348,9 @@ func (P *G1Affine) constScalarMul(api frontend.API, Q G1Affine, s *big.Int, opts negPhiQ.AddAssign(api, Acc) } Acc.Select(api, k[1].Bit(0), Acc, negPhiQ) - P.X, P.Y = Acc.X, Acc.Y + p.X, p.Y = Acc.X, Acc.Y - return P + return p } // Assign a value to self (witness assignment) @@ -396,33 +396,33 @@ func (p *G1Affine) DoubleAndAdd(api frontend.API, p1, p2 *G1Affine) *G1Affine { } // ScalarMulBase computes s * g1 and returns it, where g1 is the fixed generator. It doesn't modify s. -func (P *G1Affine) ScalarMulBase(api frontend.API, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) ScalarMulBase(api frontend.API, s frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { _, _, g1aff, _ := bls24315.Generators() generator := G1Affine{ X: g1aff.X.BigInt(new(big.Int)), Y: g1aff.Y.BigInt(new(big.Int)), } - return P.ScalarMul(api, generator, s, opts...) + return p.ScalarMul(api, generator, s, opts...) } -func (P *G1Affine) jointScalarMul(api frontend.API, Q, R G1Affine, s, t frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) jointScalarMul(api frontend.API, Q, R G1Affine, s, t frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) } if cfg.CompleteArithmetic { var tmp G1Affine - P.ScalarMul(api, Q, s, opts...) + p.ScalarMul(api, Q, s, opts...) tmp.ScalarMul(api, R, t, opts...) - P.AddUnified(api, tmp) + p.AddUnified(api, tmp) } else { - P.jointScalarMulUnsafe(api, Q, R, s, t) + p.jointScalarMulUnsafe(api, Q, R, s, t) } - return P + return p } // P = [s]Q + [t]R using Shamir's trick -func (P *G1Affine) jointScalarMulUnsafe(api frontend.API, Q, R G1Affine, s, t frontend.Variable) *G1Affine { +func (p *G1Affine) jointScalarMulUnsafe(api frontend.API, Q, R G1Affine, s, t frontend.Variable) *G1Affine { cc := getInnerCurveConfig(api.Compiler().Field()) s1, s2 := callDecomposeScalar(api, s, false) t1, t2 := callDecomposeScalar(api, t, false) @@ -485,15 +485,15 @@ func (P *G1Affine) jointScalarMulUnsafe(api frontend.API, Q, R G1Affine, s, t fr tablePhiR[0].AddAssign(api, Acc) Acc.Select(api, t2bits[0], Acc, tablePhiR[0]) - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } // scalarBitsMul computes [s]Q and returns it where sBits is the bit decomposition of s. It doesn't modify Q nor sBits. // The method is similar to varScalarMul. -func (P *G1Affine) scalarBitsMul(api frontend.API, Q G1Affine, s1bits, s2bits []frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { +func (p *G1Affine) scalarBitsMul(api frontend.API, Q G1Affine, s1bits, s2bits []frontend.Variable, opts ...algopts.AlgebraOption) *G1Affine { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) @@ -592,8 +592,8 @@ func (P *G1Affine) scalarBitsMul(api frontend.API, Q G1Affine, s1bits, s2bits [] } - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } diff --git a/std/algebra/native/sw_bls24315/g2.go b/std/algebra/native/sw_bls24315/g2.go index 53670a8d53..7f39a2200a 100644 --- a/std/algebra/native/sw_bls24315/g2.go +++ b/std/algebra/native/sw_bls24315/g2.go @@ -146,11 +146,11 @@ func (p *g2AffP) Double(api frontend.API, p1 g2AffP) *g2AffP { // The method chooses an implementation based on scalar s. If it is constant, // then the compiled circuit depends on s. If it is variable type, then // the circuit is independent of the inputs. -func (P *g2AffP) ScalarMul(api frontend.API, Q g2AffP, s interface{}, opts ...algopts.AlgebraOption) *g2AffP { +func (p *g2AffP) ScalarMul(api frontend.API, Q g2AffP, s interface{}, opts ...algopts.AlgebraOption) *g2AffP { if n, ok := api.Compiler().ConstantValue(s); ok { - return P.constScalarMul(api, Q, n, opts...) + return p.constScalarMul(api, Q, n, opts...) } else { - return P.varScalarMul(api, Q, s, opts...) + return p.varScalarMul(api, Q, s, opts...) } } @@ -163,7 +163,7 @@ func (P *g2AffP) ScalarMul(api frontend.API, Q g2AffP, s interface{}, opts ...al // // [Halo]: https://eprint.iacr.org/2019/1021.pdf // [EVM]: https://ethereum.github.io/yellowpaper/paper.pdf -func (P *g2AffP) varScalarMul(api frontend.API, Q g2AffP, s frontend.Variable, opts ...algopts.AlgebraOption) *g2AffP { +func (p *g2AffP) varScalarMul(api frontend.API, Q g2AffP, s frontend.Variable, opts ...algopts.AlgebraOption) *g2AffP { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) @@ -313,23 +313,23 @@ func (P *g2AffP) varScalarMul(api frontend.API, Q g2AffP, s frontend.Variable, o Acc.Select(api, selector, g2AffP{X: zeroE4, Y: zeroE4}, Acc) } - P.X = Acc.X - P.Y = Acc.Y + p.X = Acc.X + p.Y = Acc.Y - return P + return p } // constScalarMul sets P = [s] Q and returns P. -func (P *g2AffP) constScalarMul(api frontend.API, Q g2AffP, s *big.Int, opts ...algopts.AlgebraOption) *g2AffP { +func (p *g2AffP) constScalarMul(api frontend.API, Q g2AffP, s *big.Int, opts ...algopts.AlgebraOption) *g2AffP { cfg, err := algopts.NewConfig(opts...) if err != nil { panic(err) } if s.BitLen() == 0 { zero := fields_bls24315.E4{B0: fields_bls24315.E2{A0: 0, A1: 0}, B1: fields_bls24315.E2{A0: 0, A1: 0}} - P.X = zero - P.Y = zero - return P + p.X = zero + p.Y = zero + return p } // see the comments in varScalarMul. However, two-bit lookup is cheaper if // bits are constant and here it makes sense to use the table in the main @@ -413,9 +413,9 @@ func (P *g2AffP) constScalarMul(api frontend.API, Q g2AffP, s *big.Int, opts ... negPhiQ.AddAssign(api, Acc) } Acc.Select(api, k[1].Bit(0), Acc, negPhiQ) - P.X, P.Y = Acc.X, Acc.Y + p.X, p.Y = Acc.X, Acc.Y - return P + return p } // Assign a value to self (witness assignment) @@ -469,7 +469,7 @@ func (p *g2AffP) DoubleAndAdd(api frontend.API, p1, p2 *g2AffP) *g2AffP { } // ScalarMulBase computes s * g2 and returns it, where g2 is the fixed generator. It doesn't modify s. -func (P *g2AffP) ScalarMulBase(api frontend.API, s frontend.Variable) *g2AffP { +func (p *g2AffP) ScalarMulBase(api frontend.API, s frontend.Variable) *g2AffP { points := getTwistPoints() @@ -532,8 +532,8 @@ func (P *g2AffP) ScalarMulBase(api frontend.API, s frontend.Variable) *g2AffP { tmp.AddAssign(api, res) res.Select(api, sBits[0], res, tmp) - P.X = res.X - P.Y = res.Y + p.X = res.X + p.Y = res.Y - return P + return p } diff --git a/std/algebra/native/sw_bls24315/pairing2.go b/std/algebra/native/sw_bls24315/pairing2.go index bdc3d21fa5..d59fa549d8 100644 --- a/std/algebra/native/sw_bls24315/pairing2.go +++ b/std/algebra/native/sw_bls24315/pairing2.go @@ -255,71 +255,71 @@ func NewPairing(api frontend.API) *Pairing { } } -func (c *Pairing) IsEqual(x, y *GT) frontend.Variable { - diff0 := c.api.Sub(&x.D0.C0.B0.A0, &y.D0.C0.B0.A0) - diff1 := c.api.Sub(&x.D0.C0.B0.A1, &y.D0.C0.B0.A1) - diff2 := c.api.Sub(&x.D0.C0.B0.A0, &y.D0.C0.B0.A0) - diff3 := c.api.Sub(&x.D0.C0.B1.A1, &y.D0.C0.B1.A1) - diff4 := c.api.Sub(&x.D0.C0.B1.A0, &y.D0.C0.B1.A0) - diff5 := c.api.Sub(&x.D0.C0.B1.A1, &y.D0.C0.B1.A1) - diff6 := c.api.Sub(&x.D0.C1.B0.A0, &y.D0.C1.B0.A0) - diff7 := c.api.Sub(&x.D0.C1.B0.A1, &y.D0.C1.B0.A1) - diff8 := c.api.Sub(&x.D0.C1.B0.A0, &y.D0.C1.B0.A0) - diff9 := c.api.Sub(&x.D0.C1.B1.A1, &y.D0.C1.B1.A1) - diff10 := c.api.Sub(&x.D0.C1.B1.A0, &y.D0.C1.B1.A0) - diff11 := c.api.Sub(&x.D0.C1.B1.A1, &y.D0.C1.B1.A1) - diff12 := c.api.Sub(&x.D1.C0.B0.A0, &y.D1.C0.B0.A0) - diff13 := c.api.Sub(&x.D1.C0.B0.A1, &y.D1.C0.B0.A1) - diff14 := c.api.Sub(&x.D1.C0.B0.A0, &y.D1.C0.B0.A0) - diff15 := c.api.Sub(&x.D1.C0.B1.A1, &y.D1.C0.B1.A1) - diff16 := c.api.Sub(&x.D1.C0.B1.A0, &y.D1.C0.B1.A0) - diff17 := c.api.Sub(&x.D1.C0.B1.A1, &y.D1.C0.B1.A1) - diff18 := c.api.Sub(&x.D1.C1.B0.A0, &y.D1.C1.B0.A0) - diff19 := c.api.Sub(&x.D1.C1.B0.A1, &y.D1.C1.B0.A1) - diff20 := c.api.Sub(&x.D1.C1.B0.A0, &y.D1.C1.B0.A0) - diff21 := c.api.Sub(&x.D1.C1.B1.A1, &y.D1.C1.B1.A1) - diff22 := c.api.Sub(&x.D1.C1.B1.A0, &y.D1.C1.B1.A0) - diff23 := c.api.Sub(&x.D1.C1.B1.A1, &y.D1.C1.B1.A1) - - isZero0 := c.api.IsZero(diff0) - isZero1 := c.api.IsZero(diff1) - isZero2 := c.api.IsZero(diff2) - isZero3 := c.api.IsZero(diff3) - isZero4 := c.api.IsZero(diff4) - isZero5 := c.api.IsZero(diff5) - isZero6 := c.api.IsZero(diff6) - isZero7 := c.api.IsZero(diff7) - isZero8 := c.api.IsZero(diff8) - isZero9 := c.api.IsZero(diff9) - isZero10 := c.api.IsZero(diff10) - isZero11 := c.api.IsZero(diff11) - isZero12 := c.api.IsZero(diff12) - isZero13 := c.api.IsZero(diff13) - isZero14 := c.api.IsZero(diff14) - isZero15 := c.api.IsZero(diff15) - isZero16 := c.api.IsZero(diff16) - isZero17 := c.api.IsZero(diff17) - isZero18 := c.api.IsZero(diff18) - isZero19 := c.api.IsZero(diff19) - isZero20 := c.api.IsZero(diff20) - isZero21 := c.api.IsZero(diff21) - isZero22 := c.api.IsZero(diff22) - isZero23 := c.api.IsZero(diff23) - - return c.api.And( - c.api.And( - c.api.And( - c.api.And(c.api.And(isZero0, isZero1), c.api.And(isZero2, isZero3)), - c.api.And(c.api.And(isZero4, isZero5), c.api.And(isZero6, isZero7)), +func (pr *Pairing) IsEqual(x, y *GT) frontend.Variable { + diff0 := pr.api.Sub(&x.D0.C0.B0.A0, &y.D0.C0.B0.A0) + diff1 := pr.api.Sub(&x.D0.C0.B0.A1, &y.D0.C0.B0.A1) + diff2 := pr.api.Sub(&x.D0.C0.B0.A0, &y.D0.C0.B0.A0) + diff3 := pr.api.Sub(&x.D0.C0.B1.A1, &y.D0.C0.B1.A1) + diff4 := pr.api.Sub(&x.D0.C0.B1.A0, &y.D0.C0.B1.A0) + diff5 := pr.api.Sub(&x.D0.C0.B1.A1, &y.D0.C0.B1.A1) + diff6 := pr.api.Sub(&x.D0.C1.B0.A0, &y.D0.C1.B0.A0) + diff7 := pr.api.Sub(&x.D0.C1.B0.A1, &y.D0.C1.B0.A1) + diff8 := pr.api.Sub(&x.D0.C1.B0.A0, &y.D0.C1.B0.A0) + diff9 := pr.api.Sub(&x.D0.C1.B1.A1, &y.D0.C1.B1.A1) + diff10 := pr.api.Sub(&x.D0.C1.B1.A0, &y.D0.C1.B1.A0) + diff11 := pr.api.Sub(&x.D0.C1.B1.A1, &y.D0.C1.B1.A1) + diff12 := pr.api.Sub(&x.D1.C0.B0.A0, &y.D1.C0.B0.A0) + diff13 := pr.api.Sub(&x.D1.C0.B0.A1, &y.D1.C0.B0.A1) + diff14 := pr.api.Sub(&x.D1.C0.B0.A0, &y.D1.C0.B0.A0) + diff15 := pr.api.Sub(&x.D1.C0.B1.A1, &y.D1.C0.B1.A1) + diff16 := pr.api.Sub(&x.D1.C0.B1.A0, &y.D1.C0.B1.A0) + diff17 := pr.api.Sub(&x.D1.C0.B1.A1, &y.D1.C0.B1.A1) + diff18 := pr.api.Sub(&x.D1.C1.B0.A0, &y.D1.C1.B0.A0) + diff19 := pr.api.Sub(&x.D1.C1.B0.A1, &y.D1.C1.B0.A1) + diff20 := pr.api.Sub(&x.D1.C1.B0.A0, &y.D1.C1.B0.A0) + diff21 := pr.api.Sub(&x.D1.C1.B1.A1, &y.D1.C1.B1.A1) + diff22 := pr.api.Sub(&x.D1.C1.B1.A0, &y.D1.C1.B1.A0) + diff23 := pr.api.Sub(&x.D1.C1.B1.A1, &y.D1.C1.B1.A1) + + isZero0 := pr.api.IsZero(diff0) + isZero1 := pr.api.IsZero(diff1) + isZero2 := pr.api.IsZero(diff2) + isZero3 := pr.api.IsZero(diff3) + isZero4 := pr.api.IsZero(diff4) + isZero5 := pr.api.IsZero(diff5) + isZero6 := pr.api.IsZero(diff6) + isZero7 := pr.api.IsZero(diff7) + isZero8 := pr.api.IsZero(diff8) + isZero9 := pr.api.IsZero(diff9) + isZero10 := pr.api.IsZero(diff10) + isZero11 := pr.api.IsZero(diff11) + isZero12 := pr.api.IsZero(diff12) + isZero13 := pr.api.IsZero(diff13) + isZero14 := pr.api.IsZero(diff14) + isZero15 := pr.api.IsZero(diff15) + isZero16 := pr.api.IsZero(diff16) + isZero17 := pr.api.IsZero(diff17) + isZero18 := pr.api.IsZero(diff18) + isZero19 := pr.api.IsZero(diff19) + isZero20 := pr.api.IsZero(diff20) + isZero21 := pr.api.IsZero(diff21) + isZero22 := pr.api.IsZero(diff22) + isZero23 := pr.api.IsZero(diff23) + + return pr.api.And( + pr.api.And( + pr.api.And( + pr.api.And(pr.api.And(isZero0, isZero1), pr.api.And(isZero2, isZero3)), + pr.api.And(pr.api.And(isZero4, isZero5), pr.api.And(isZero6, isZero7)), ), - c.api.And( - c.api.And(c.api.And(isZero8, isZero9), c.api.And(isZero10, isZero11)), - c.api.And(c.api.And(isZero12, isZero13), c.api.And(isZero14, isZero15)), + pr.api.And( + pr.api.And(pr.api.And(isZero8, isZero9), pr.api.And(isZero10, isZero11)), + pr.api.And(pr.api.And(isZero12, isZero13), pr.api.And(isZero14, isZero15)), ), ), - c.api.And( - c.api.And(c.api.And(isZero16, isZero17), c.api.And(isZero18, isZero19)), - c.api.And(c.api.And(isZero20, isZero21), c.api.And(isZero22, isZero23)), + pr.api.And( + pr.api.And(pr.api.And(isZero16, isZero17), pr.api.And(isZero18, isZero19)), + pr.api.And(pr.api.And(isZero20, isZero21), pr.api.And(isZero22, isZero23)), ), ) } @@ -327,7 +327,7 @@ func (c *Pairing) IsEqual(x, y *GT) frontend.Variable { // MillerLoop computes the Miller loop between the pairs of inputs. It doesn't // modify the inputs. It returns an error if there is a mismatch between the // lengths of the inputs. -func (p *Pairing) MillerLoop(P []*G1Affine, Q []*G2Affine) (*GT, error) { +func (pr *Pairing) MillerLoop(P []*G1Affine, Q []*G2Affine) (*GT, error) { inP := make([]G1Affine, len(P)) for i := range P { inP[i] = *P[i] @@ -336,19 +336,19 @@ func (p *Pairing) MillerLoop(P []*G1Affine, Q []*G2Affine) (*GT, error) { for i := range Q { inQ[i] = *Q[i] } - res, err := MillerLoop(p.api, inP, inQ) + res, err := MillerLoop(pr.api, inP, inQ) return &res, err } // FinalExponentiation performs the final exponentiation on the target group // element. It doesn't modify the input. -func (p *Pairing) FinalExponentiation(e *GT) *GT { - res := FinalExponentiation(p.api, *e) +func (pr *Pairing) FinalExponentiation(e *GT) *GT { + res := FinalExponentiation(pr.api, *e) return &res } // Pair computes a full multi-pairing on the input pairs. -func (p *Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GT, error) { +func (pr *Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GT, error) { inP := make([]G1Affine, len(P)) for i := range P { inP[i] = *P[i] @@ -357,14 +357,14 @@ func (p *Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GT, error) { for i := range Q { inQ[i] = *Q[i] } - res, err := Pair(p.api, inP, inQ) + res, err := Pair(pr.api, inP, inQ) return &res, err } // PairingCheck computes the multi-pairing of the input pairs and asserts that // the result is an identity element in the target group. It returns an error if // there is a mismatch between the lengths of the inputs. -func (p *Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { +func (pr *Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { inP := make([]G1Affine, len(P)) for i := range P { inP[i] = *P[i] @@ -373,19 +373,19 @@ func (p *Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { for i := range Q { inQ[i] = *Q[i] } - res, err := Pair(p.api, inP, inQ) + res, err := Pair(pr.api, inP, inQ) if err != nil { return err } var one fields_bls24315.E24 one.SetOne() - res.AssertIsEqual(p.api, one) + res.AssertIsEqual(pr.api, one) return nil } // AssertIsEqual asserts the equality of the target group elements. -func (p *Pairing) AssertIsEqual(e1, e2 *GT) { - e1.AssertIsEqual(p.api, *e2) +func (pr *Pairing) AssertIsEqual(e1, e2 *GT) { + e1.AssertIsEqual(pr.api, *e2) } func (pr Pairing) MuxG2(sel frontend.Variable, inputs ...*G2Affine) *G2Affine { if len(inputs) == 0 { @@ -570,11 +570,11 @@ func (pr Pairing) MuxGt(sel frontend.Variable, inputs ...*GT) *GT { return &ret } -func (p *Pairing) AssertIsOnG1(P *G1Affine) { +func (pr *Pairing) AssertIsOnG1(P *G1Affine) { panic("not implemented") } -func (p *Pairing) AssertIsOnG2(P *G2Affine) { +func (pr *Pairing) AssertIsOnG2(P *G2Affine) { panic("not implemented") } diff --git a/std/math/emulated/field_test.go b/std/math/emulated/field_test.go index 725e7ea9a6..a0a355f7fe 100644 --- a/std/math/emulated/field_test.go +++ b/std/math/emulated/field_test.go @@ -41,7 +41,7 @@ func (c *ConstantCircuit) Define(api frontend.API) error { if !ok { return errors.New("42 should be constant") } - if !(b1.IsUint64() && b1.Uint64() == 42) { + if !b1.IsUint64() || b1.Uint64() != 42 { return errors.New("42 != constant(42)") } } diff --git a/test/assert.go b/test/assert.go index 8803205c58..0e38151684 100644 --- a/test/assert.go +++ b/test/assert.go @@ -47,9 +47,9 @@ func NewAssert(t *testing.T) *Assert { // Run runs the test function fn as a subtest. The subtest is parametrized by // the description strings descs. -func (a *Assert) Run(fn func(assert *Assert), descs ...string) { +func (assert *Assert) Run(fn func(assert *Assert), descs ...string) { desc := strings.Join(descs, "/") - a.t.Run(desc, func(t *testing.T) { + assert.t.Run(desc, func(t *testing.T) { assert := &Assert{t, require.New(t)} fn(assert) }) diff --git a/test/engine.go b/test/engine.go index 79322af440..267a75a98d 100644 --- a/test/engine.go +++ b/test/engine.go @@ -604,9 +604,12 @@ func (e *engine) FieldBitLen() int { } func (e *engine) mustBeBoolean(b *big.Int) { - if !b.IsUint64() || !(b.Uint64() == 0 || b.Uint64() == 1) { - panic(fmt.Sprintf("[assertIsBoolean] %s", b.String())) + if b.IsUint64() { + if v := b.Uint64(); v == 0 || v == 1 { + return + } } + panic(fmt.Sprintf("[assertIsBoolean] %s", b.String())) } func (e *engine) modulus() *big.Int {