From 5ac34ddee15a946371de87f69283d158a1f24db2 Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Mon, 6 Jan 2025 16:05:30 +0100 Subject: [PATCH 1/8] added the compiler for logderivativesum --- prover/protocol/column/column.go | 16 ++ .../compiler/logderivative_sum.go/compile.go | 49 ++++++ prover/protocol/compiler/lookup/compiler.go | 6 +- prover/protocol/compiler/lookup/prover.go | 12 +- prover/protocol/compiler/lookup/verifier.go | 8 +- prover/protocol/compiler/lookup/z_packing.go | 6 +- prover/protocol/distributed/preparation.go | 160 +++++++++++++++++- prover/protocol/query/logderiv_sum.go | 9 +- 8 files changed, 241 insertions(+), 25 deletions(-) create mode 100644 prover/protocol/compiler/logderivative_sum.go/compile.go diff --git a/prover/protocol/column/column.go b/prover/protocol/column/column.go index 906bf9102..18af77a92 100644 --- a/prover/protocol/column/column.go +++ b/prover/protocol/column/column.go @@ -4,6 +4,7 @@ import ( "reflect" "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" + "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/coin" "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/variables" @@ -172,3 +173,18 @@ func ExprIsOnSameLengthHandles(board *symbolic.ExpressionBoard) int { return length } + +// return the runtime assignments of a linear combination column +// that is computed on the fly from the columns stored in hs +func RandLinCombColAssignment(run ifaces.Runtime, coinVal field.Element, hs []ifaces.Column) smartvectors.SmartVector { + var colTableWit smartvectors.SmartVector + var witnessCollapsed smartvectors.SmartVector + x := field.One() + witnessCollapsed = smartvectors.NewConstant(field.Zero(), hs[0].Size()) + for tableCol := range hs { + colTableWit = hs[tableCol].GetColAssignment(run) + witnessCollapsed = smartvectors.Add(witnessCollapsed, smartvectors.Mul(colTableWit, smartvectors.NewConstant(x, hs[0].Size()))) + x.Mul(&x, &coinVal) + } + return witnessCollapsed +} diff --git a/prover/protocol/compiler/logderivative_sum.go/compile.go b/prover/protocol/compiler/logderivative_sum.go/compile.go new file mode 100644 index 000000000..0308d8258 --- /dev/null +++ b/prover/protocol/compiler/logderivative_sum.go/compile.go @@ -0,0 +1,49 @@ +package logderiv + +import ( + "github.com/consensys/linea-monorepo/prover/protocol/compiler/lookup" + "github.com/consensys/linea-monorepo/prover/protocol/query" + "github.com/consensys/linea-monorepo/prover/protocol/wizard" +) + +// compile [query.LogDerivativeSum] query +func CompileLogDerivSum(comp *wizard.CompiledIOP) { + + // Collect all the lookup queries into "lookups" + for _, qName := range comp.QueriesParams.AllUnignoredKeys() { + + // Filter out non lookup queries + logDeriv, ok := comp.QueriesParams.Data(qName).(query.LogDerivativeSum) + if !ok { + continue + } + + // This ensures that the LogDerivativeSum query is not used again in the + // compilation process. We know that the query was already ignored at + // the beginning because we are iterating over the unignored keys. + comp.QueriesParams.MarkAsIgnored(qName) + zEntries := logDeriv.Inputs + va := lookup.FinalEvaluationCheck{} + for _, entry := range zEntries { + zC := &lookup.ZCtx{ + Round: entry.Round, + Size: entry.Size, + SigmaNumerator: entry.Numerator, + SigmaDenominator: entry.Denominator, + } + + // z-packing compile + zC.Compile(comp) + // prover step; Z assignments + zAssignmentTask := lookup.ZAssignmentTask(*zC) + comp.SubProvers.AppendToInner(zC.Round, func(run *wizard.ProverRuntime) { + zAssignmentTask.Run(run) + }) + va.ZOpenings = append(va.ZOpenings, zC.ZOpenings...) + } + // verifer step + lastRound := comp.NumRounds() - 1 + comp.RegisterVerifierAction(lastRound, &va) + } + +} diff --git a/prover/protocol/compiler/lookup/compiler.go b/prover/protocol/compiler/lookup/compiler.go index a39838b48..441c42556 100644 --- a/prover/protocol/compiler/lookup/compiler.go +++ b/prover/protocol/compiler/lookup/compiler.go @@ -36,7 +36,7 @@ func CompileLogDerivative(comp *wizard.CompiledIOP) { zCatalog = map[[2]int]*ZCtx{} zEntries = [][2]int{} // verifier actions - va = finalEvaluationCheck{} + va = FinalEvaluationCheck{} ) // Skip the compilation phase if no lookup constraint is being used. Otherwise @@ -99,11 +99,11 @@ func CompileLogDerivative(comp *wizard.CompiledIOP) { for _, entry := range zEntries { zC := zCatalog[entry] // z-packing compile - zC.compile(comp) + zC.Compile(comp) // entry[0]:round, entry[1]: size // the round that Gamma was registered. round := entry[0] - proverActions[round].pushZAssignment(zAssignmentTask(*zC)) + proverActions[round].pushZAssignment(ZAssignmentTask(*zC)) va.ZOpenings = append(va.ZOpenings, zC.ZOpenings...) va.Name = zC.Name } diff --git a/prover/protocol/compiler/lookup/prover.go b/prover/protocol/compiler/lookup/prover.go index 57bd5d612..dfa7d382a 100644 --- a/prover/protocol/compiler/lookup/prover.go +++ b/prover/protocol/compiler/lookup/prover.go @@ -32,7 +32,7 @@ type proverTaskAtRound struct { // ZAssignmentTasks lists all the tasks consisting of assigning the // columns SigmaS and SigmaT for the given round. - ZAssignmentTasks []zAssignmentTask + ZAssignmentTasks []ZAssignmentTask } // Run implements the [wizard.ProverAction interface]. The tasks will spawn @@ -94,7 +94,7 @@ func (p proverTaskAtRound) Run(run *wizard.ProverRuntime) { wg.Done() }() - p.ZAssignmentTasks[i].run(run) + p.ZAssignmentTasks[i].Run(run) }(i) } @@ -111,7 +111,7 @@ func (p *proverTaskAtRound) pushMAssignment(m MAssignmentTask) { } // pushZAssignment appends an [sigmaAssignmentTask] to the list of tasks -func (p *proverTaskAtRound) pushZAssignment(s zAssignmentTask) { +func (p *proverTaskAtRound) pushZAssignment(s ZAssignmentTask) { p.ZAssignmentTasks = append(p.ZAssignmentTasks, s) } @@ -298,12 +298,12 @@ func (a MAssignmentTask) Run(run *wizard.ProverRuntime) { } -// zAssignmentTask represents a prover task of assignming the columns +// ZAssignmentTask represents a prover task of assignming the columns // SigmaS and SigmaT for a specific lookup table. // sigmaAssignment -type zAssignmentTask ZCtx +type ZAssignmentTask ZCtx -func (z zAssignmentTask) run(run *wizard.ProverRuntime) { +func (z ZAssignmentTask) Run(run *wizard.ProverRuntime) { parallel.Execute(len(z.ZDenominatorBoarded), func(start, stop int) { for frag := start; frag < stop; frag++ { diff --git a/prover/protocol/compiler/lookup/verifier.go b/prover/protocol/compiler/lookup/verifier.go index b5179574b..43fe701cc 100644 --- a/prover/protocol/compiler/lookup/verifier.go +++ b/prover/protocol/compiler/lookup/verifier.go @@ -9,14 +9,14 @@ import ( "github.com/consensys/linea-monorepo/prover/protocol/wizard" ) -// finalEvaluationCheck implements the [wizard.VerifierAction] interface. It +// FinalEvaluationCheck implements the [wizard.VerifierAction] interface. It // represents the consistency check between SigmaT and the SigmaS[i]. This // corresponds in the check #1 in the doc, where the verifier ensures that // summing the ending values of the SigmaS[i]s yields the same result as the // ending value of SigmaT. // // The current implementation is for packed Zs -type finalEvaluationCheck struct { +type FinalEvaluationCheck struct { // the name of a lookupTable in the pack, this can help for debugging. Name string // ZOpenings lists all the openings of all the zCtx @@ -24,7 +24,7 @@ type finalEvaluationCheck struct { } // Run implements the [wizard.VerifierAction] -func (f *finalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { +func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { // zSum stores the sum of the ending values of the zs as queried // in the protocol via the local opening queries. @@ -42,7 +42,7 @@ func (f *finalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { } // RunGnark implements the [wizard.VerifierAction] -func (f *finalEvaluationCheck) RunGnark(api frontend.API, run *wizard.WizardVerifierCircuit) { +func (f *FinalEvaluationCheck) RunGnark(api frontend.API, run *wizard.WizardVerifierCircuit) { // SigmaSKSum stores the sum of the ending values of the SigmaSs as queried // in the protocol via the diff --git a/prover/protocol/compiler/lookup/z_packing.go b/prover/protocol/compiler/lookup/z_packing.go index 2838f4834..7d62954bd 100644 --- a/prover/protocol/compiler/lookup/z_packing.go +++ b/prover/protocol/compiler/lookup/z_packing.go @@ -39,12 +39,12 @@ type ZCtx struct { Name string } -// check permutation and see how/where compile is called (see how to constracut z there) +// check permutation and see how/where Compile is called (see how to constracut z there) // when constructing z, check if z is T or S // and change T -> -M, S -> +Filter // S or T -> ({S,T} + X) -// compile should be called inside CompileGrandSum -func (z *ZCtx) compile(comp *wizard.CompiledIOP) { +// Compile should be called inside CompileGrandSum +func (z *ZCtx) Compile(comp *wizard.CompiledIOP) { var ( numZs = utils.DivCeil( diff --git a/prover/protocol/distributed/preparation.go b/prover/protocol/distributed/preparation.go index 9bd55cdae..16662758b 100644 --- a/prover/protocol/distributed/preparation.go +++ b/prover/protocol/distributed/preparation.go @@ -1,14 +1,20 @@ package distributed import ( + sv "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" + "github.com/consensys/linea-monorepo/prover/maths/common/vector" + "github.com/consensys/linea-monorepo/prover/maths/field" + "github.com/consensys/linea-monorepo/prover/protocol/column" "github.com/consensys/linea-monorepo/prover/protocol/compiler/innerproduct" "github.com/consensys/linea-monorepo/prover/protocol/compiler/lookup" "github.com/consensys/linea-monorepo/prover/protocol/compiler/mimc" "github.com/consensys/linea-monorepo/prover/protocol/compiler/specialqueries" + "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/query" "github.com/consensys/linea-monorepo/prover/protocol/wizard" "github.com/consensys/linea-monorepo/prover/protocol/wizardutils" "github.com/consensys/linea-monorepo/prover/symbolic" + "github.com/consensys/linea-monorepo/prover/utils" ) // prepare reduces any query to LPP or GL. @@ -54,7 +60,7 @@ func IntoLogDerivativeSum(comp *wizard.CompiledIOP) { checkTable = mainLookupCtx.CheckedTables[lookupTableName] round = mainLookupCtx.Rounds[lookupTableName] includedFilters = mainLookupCtx.IncludedFilters[lookupTableName] - // collapse multiColumns to single Columns + // collapse multiColumns to single Columns and commit to M. tableCtx = lookup.CompileLookupTable(comp, round, lookupTable, checkTable, includedFilters) ) @@ -125,3 +131,155 @@ func PushToZCatalog(stc lookup.SingleTableCtx, zCatalog map[[2]int]*query.LogDer zCtxEntry.Denominator = append(zCtxEntry.Denominator, symbolic.Add(stc.Gamma, stc.S[table])) } } + +// PrepareMAssignment outputs a list mapping the ID of a M column to its witness. +func PrepareMAssignment(a lookup.MAssignmentTask, run ifaces.Runtime) map[ifaces.ColID]*sv.Regular { + + var ( + // isMultiColumn flags whether the table have multiple column and + // whether the "collapsing" trick is needed. + isMultiColumn = len(a.T[0]) > 1 + + // tCollapsed contains either the assignment of T if the table is a + // single column (e.g. isMultiColumn=false) or its collapsed version + // otherwise. + tCollapsed = make([]sv.SmartVector, len(a.T)) + + // sCollapsed contains either the assignment of the Ss if the table is a + // single column (e.g. isMultiColumn=false) or their collapsed version + // otherwise. + sCollapsed = make([]sv.SmartVector, len(a.S)) + + // fragmentUnionSize contains the total number of rows contained in all + // the fragments of T combined. + fragmentUnionSize int + ) + + if !isMultiColumn { + for frag := range a.T { + tCollapsed[frag] = a.T[frag][0].GetColAssignment(run) + fragmentUnionSize += a.T[frag][0].Size() + } + + for i := range a.S { + sCollapsed[i] = a.S[i][0].GetColAssignment(run) + } + } + + if isMultiColumn { + // collapsingRandomness is the randomness used in the collapsing trick. + // It is sampled via `crypto/rand` internally to ensure it cannot be + // predicted ahead of time by an adversary. + var collapsingRandomness field.Element + if _, err := collapsingRandomness.SetRandom(); err != nil { + utils.Panic("could not sample the collapsing randomness: %v", err.Error()) + } + + for frag := range a.T { + tCollapsed[frag] = column.RandLinCombColAssignment(run, collapsingRandomness, a.T[frag]) + } + + for i := range a.S { + sCollapsed[i] = column.RandLinCombColAssignment(run, collapsingRandomness, a.S[i]) + } + } + + var ( + // m is associated with tCollapsed + // m stores the assignment to the column M as we build it. + m = make([][]field.Element, len(a.T)) + + // mapm collects the entries in the inclusion set to their positions + // in tCollapsed. If T contains duplicates, the last position is the + // one that is kept in mapM. + // + // It is used to let us know where an entry of S appears in T. The stored + // 2-uple of integers indicate [fragment, row] + mapM = make(map[field.Element][2]int, fragmentUnionSize) + + // one stores a reference to the field element equals to 1 for + // convenience so that we can use pointer on it directly. + one = field.One() + ) + + // This loops initializes mapM so that it tracks to the positions of the + // entries of T. It also preinitializes the values of ms + for frag := range a.T { + m[frag] = make([]field.Element, tCollapsed[frag].Len()) + for k := 0; k < tCollapsed[frag].Len(); k++ { + mapM[tCollapsed[frag].Get(k)] = [2]int{frag, k} + } + } + + // This loops counts all the occurences of the rows of T within S and store + // them into S. + for i := range sCollapsed { + + var ( + hasFilter = a.SFilter[i] != nil + filter []field.Element + ) + + if hasFilter { + filter = a.SFilter[i].GetColAssignment(run).IntoRegVecSaveAlloc() + } + + for k := 0; k < sCollapsed[i].Len(); k++ { + + if hasFilter && filter[k].IsZero() { + continue + } + + if hasFilter && !filter[k].IsOne() { + utils.Panic( + "the filter column `%v` has a non-binary value at position `%v`: (%v)", + a.SFilter[i].GetColID(), + k, + filter[k].String(), + ) + } + + var ( + // v stores the entry of S that we are examining and looking for + // in the look up table. + v = sCollapsed[i].Get(k) + + // posInM stores the position of `v` in the look-up table + posInM, ok = mapM[v] + ) + + if !ok { + tableRow := make([]field.Element, len(a.S[i])) + for j := range tableRow { + tableRow[j] = a.S[i][j].GetColAssignmentAt(run, k) + } + utils.Panic( + "entry %v of the table %v is not included in the table. tableRow=%v", + k, lookup.NameTable([][]ifaces.Column{a.S[i]}), vector.Prettify(tableRow), + ) + } + + mFrag, posInFragM := posInM[0], posInM[1] + m[mFrag][posInFragM].Add(&m[mFrag][posInFragM], &one) + } + + } + + for frag := range m { + mList[a.M[frag].GetColID()] = sv.NewRegular(m[frag]) + } + return mList + /* + a more professional way: + Pass all the prover message columns as part of the proof + + messages := collection.NewMapping[ifaces.ColID, ifaces.ColAssignment]() + + for _, name := range runtime.Spec.Columns.AllKeysProof() { + messageValue := runtime.Columns.MustGet(name) + messages.InsertNew(name, messageValue) + } + */ +} + +var mList map[ifaces.ColID]*sv.Regular diff --git a/prover/protocol/query/logderiv_sum.go b/prover/protocol/query/logderiv_sum.go index 9734cdc7b..6a5cb5d4f 100644 --- a/prover/protocol/query/logderiv_sum.go +++ b/prover/protocol/query/logderiv_sum.go @@ -28,14 +28,7 @@ type LogDerivativeSumInput struct { // D_{i,j} is the i-th element of the underlying column of j-th Denominator type LogDerivativeSum struct { Inputs map[[2]int]*LogDerivativeSumInput - - ZNumeratorBoarded, ZDenominatorBoarded map[[2]int][]sym.ExpressionBoard - - Zs map[[2]int][]ifaces.Column - // ZOpenings are the opening queries to the end of each Z. - ZOpenings map[[2]int][]LocalOpening - - ID ifaces.QueryID + ID ifaces.QueryID } // the result of the global Sum From fb194e49c42e898b2b999db8c5494fa085705aa8 Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Mon, 6 Jan 2025 16:26:16 +0100 Subject: [PATCH 2/8] replace zero check against the expected sum --- .../compiler/logderivative_sum.go/compile.go | 47 ++++++++++++++++++- prover/protocol/compiler/lookup/compiler.go | 2 +- prover/protocol/compiler/lookup/verifier.go | 8 ++-- .../compiler/inclusion/inclusion.go | 2 +- 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/prover/protocol/compiler/logderivative_sum.go/compile.go b/prover/protocol/compiler/logderivative_sum.go/compile.go index 0308d8258..af1e7e3f7 100644 --- a/prover/protocol/compiler/logderivative_sum.go/compile.go +++ b/prover/protocol/compiler/logderivative_sum.go/compile.go @@ -1,6 +1,10 @@ package logderiv import ( + "fmt" + + "github.com/consensys/gnark/frontend" + "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/compiler/lookup" "github.com/consensys/linea-monorepo/prover/protocol/query" "github.com/consensys/linea-monorepo/prover/protocol/wizard" @@ -23,7 +27,7 @@ func CompileLogDerivSum(comp *wizard.CompiledIOP) { // the beginning because we are iterating over the unignored keys. comp.QueriesParams.MarkAsIgnored(qName) zEntries := logDeriv.Inputs - va := lookup.FinalEvaluationCheck{} + va := FinalEvaluationCheck{} for _, entry := range zEntries { zC := &lookup.ZCtx{ Round: entry.Round, @@ -47,3 +51,44 @@ func CompileLogDerivSum(comp *wizard.CompiledIOP) { } } + +type FinalEvaluationCheck struct { + // the name of a lookupTable in the pack, this can help for debugging. + Name string + // ZOpenings lists all the openings of all the zCtx + ZOpenings []query.LocalOpening + // the expected sum + Sum field.Element +} + +// Run implements the [wizard.VerifierAction] +func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { + + // zSum stores the sum of the ending values of the zs as queried + // in the protocol via the local opening queries. + zSum := field.Zero() + for k := range f.ZOpenings { + temp := run.GetLocalPointEvalParams(f.ZOpenings[k].ID).Y + zSum.Add(&zSum, &temp) + } + + if zSum != f.Sum { + return fmt.Errorf("log-derivate lookup, the final evaluation check failed for %v,", f.Name) + } + + return nil +} + +// RunGnark implements the [wizard.VerifierAction] +func (f *FinalEvaluationCheck) RunGnark(api frontend.API, run *wizard.WizardVerifierCircuit) { + + // SigmaSKSum stores the sum of the ending values of the SigmaSs as queried + // in the protocol via the + zSum := frontend.Variable(f.Sum) + for k := range f.ZOpenings { + temp := run.GetLocalPointEvalParams(f.ZOpenings[k].ID).Y + zSum = api.Add(zSum, temp) + } + + api.AssertIsEqual(zSum, 0) +} diff --git a/prover/protocol/compiler/lookup/compiler.go b/prover/protocol/compiler/lookup/compiler.go index 441c42556..772dce3ae 100644 --- a/prover/protocol/compiler/lookup/compiler.go +++ b/prover/protocol/compiler/lookup/compiler.go @@ -36,7 +36,7 @@ func CompileLogDerivative(comp *wizard.CompiledIOP) { zCatalog = map[[2]int]*ZCtx{} zEntries = [][2]int{} // verifier actions - va = FinalEvaluationCheck{} + va = finalEvaluationCheck{} ) // Skip the compilation phase if no lookup constraint is being used. Otherwise diff --git a/prover/protocol/compiler/lookup/verifier.go b/prover/protocol/compiler/lookup/verifier.go index 43fe701cc..b5179574b 100644 --- a/prover/protocol/compiler/lookup/verifier.go +++ b/prover/protocol/compiler/lookup/verifier.go @@ -9,14 +9,14 @@ import ( "github.com/consensys/linea-monorepo/prover/protocol/wizard" ) -// FinalEvaluationCheck implements the [wizard.VerifierAction] interface. It +// finalEvaluationCheck implements the [wizard.VerifierAction] interface. It // represents the consistency check between SigmaT and the SigmaS[i]. This // corresponds in the check #1 in the doc, where the verifier ensures that // summing the ending values of the SigmaS[i]s yields the same result as the // ending value of SigmaT. // // The current implementation is for packed Zs -type FinalEvaluationCheck struct { +type finalEvaluationCheck struct { // the name of a lookupTable in the pack, this can help for debugging. Name string // ZOpenings lists all the openings of all the zCtx @@ -24,7 +24,7 @@ type FinalEvaluationCheck struct { } // Run implements the [wizard.VerifierAction] -func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { +func (f *finalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { // zSum stores the sum of the ending values of the zs as queried // in the protocol via the local opening queries. @@ -42,7 +42,7 @@ func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { } // RunGnark implements the [wizard.VerifierAction] -func (f *FinalEvaluationCheck) RunGnark(api frontend.API, run *wizard.WizardVerifierCircuit) { +func (f *finalEvaluationCheck) RunGnark(api frontend.API, run *wizard.WizardVerifierCircuit) { // SigmaSKSum stores the sum of the ending values of the SigmaSs as queried // in the protocol via the diff --git a/prover/protocol/distributed/compiler/inclusion/inclusion.go b/prover/protocol/distributed/compiler/inclusion/inclusion.go index f2685ff34..73086fccb 100644 --- a/prover/protocol/distributed/compiler/inclusion/inclusion.go +++ b/prover/protocol/distributed/compiler/inclusion/inclusion.go @@ -25,7 +25,7 @@ type DistributionInputs struct { } // GetShareOfLogDerivativeSum extracts the share of the given modules from the given LogDerivativeSum query. -// It insert a new LogDerivativeSum for the extracted share. +// It inserts a new LogDerivativeSum for the extracted share. func GetShareOfLogDerivativeSum(in DistributionInputs) { var ( initialComp = in.InitialComp From 8a6246a6190cd117804e78b82d6fe02df073152b Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Mon, 6 Jan 2025 16:55:51 +0100 Subject: [PATCH 3/8] fixed the verifier check against the claimed sum --- .../compiler/logderivative_sum.go/compile.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/prover/protocol/compiler/logderivative_sum.go/compile.go b/prover/protocol/compiler/logderivative_sum.go/compile.go index af1e7e3f7..1f5e61516 100644 --- a/prover/protocol/compiler/logderivative_sum.go/compile.go +++ b/prover/protocol/compiler/logderivative_sum.go/compile.go @@ -6,6 +6,7 @@ import ( "github.com/consensys/gnark/frontend" "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/compiler/lookup" + "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/query" "github.com/consensys/linea-monorepo/prover/protocol/wizard" ) @@ -45,6 +46,7 @@ func CompileLogDerivSum(comp *wizard.CompiledIOP) { }) va.ZOpenings = append(va.ZOpenings, zC.ZOpenings...) } + va.LogDeriveSumID = qName // verifer step lastRound := comp.NumRounds() - 1 comp.RegisterVerifierAction(lastRound, &va) @@ -57,8 +59,8 @@ type FinalEvaluationCheck struct { Name string // ZOpenings lists all the openings of all the zCtx ZOpenings []query.LocalOpening - // the expected sum - Sum field.Element + // query ID + LogDeriveSumID ifaces.QueryID } // Run implements the [wizard.VerifierAction] @@ -72,7 +74,8 @@ func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { zSum.Add(&zSum, &temp) } - if zSum != f.Sum { + claimedSum := run.GetLogDerivSumParams(f.LogDeriveSumID).Sum + if zSum != claimedSum { return fmt.Errorf("log-derivate lookup, the final evaluation check failed for %v,", f.Name) } @@ -82,13 +85,14 @@ func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { // RunGnark implements the [wizard.VerifierAction] func (f *FinalEvaluationCheck) RunGnark(api frontend.API, run *wizard.WizardVerifierCircuit) { + claimedSum := run.GetLogDerivSumParams(f.LogDeriveSumID) // SigmaSKSum stores the sum of the ending values of the SigmaSs as queried // in the protocol via the - zSum := frontend.Variable(f.Sum) + zSum := frontend.Variable(field.Zero()) for k := range f.ZOpenings { temp := run.GetLocalPointEvalParams(f.ZOpenings[k].ID).Y zSum = api.Add(zSum, temp) } - api.AssertIsEqual(zSum, 0) + api.AssertIsEqual(zSum, claimedSum) } From 175361972c582a0807e43f626ec88948b17c1786 Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Tue, 7 Jan 2025 10:33:35 +0100 Subject: [PATCH 4/8] testing the logderivativesum compilation --- .../compiler/logderivative_sum.go/compile.go | 21 +++--- .../logderivative_sum.go/logderivsum_test.go | 75 +++++++++++++++++++ prover/protocol/query/gnark_params.go | 6 +- prover/protocol/wizard/gnark_verifier.go | 6 +- 4 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 prover/protocol/compiler/logderivative_sum.go/logderivsum_test.go diff --git a/prover/protocol/compiler/logderivative_sum.go/compile.go b/prover/protocol/compiler/logderivative_sum.go/compile.go index 1f5e61516..04fc06692 100644 --- a/prover/protocol/compiler/logderivative_sum.go/compile.go +++ b/prover/protocol/compiler/logderivative_sum.go/compile.go @@ -14,10 +14,10 @@ import ( // compile [query.LogDerivativeSum] query func CompileLogDerivSum(comp *wizard.CompiledIOP) { - // Collect all the lookup queries into "lookups" + // Collect all the logDerivativeSum queries for _, qName := range comp.QueriesParams.AllUnignoredKeys() { - // Filter out non lookup queries + // Filter out non other types of queries logDeriv, ok := comp.QueriesParams.Data(qName).(query.LogDerivativeSum) if !ok { continue @@ -27,6 +27,7 @@ func CompileLogDerivSum(comp *wizard.CompiledIOP) { // compilation process. We know that the query was already ignored at // the beginning because we are iterating over the unignored keys. comp.QueriesParams.MarkAsIgnored(qName) + // get the Numerator and Denominator from the input and prepare their compilation. zEntries := logDeriv.Inputs va := FinalEvaluationCheck{} for _, entry := range zEntries { @@ -37,17 +38,19 @@ func CompileLogDerivSum(comp *wizard.CompiledIOP) { SigmaDenominator: entry.Denominator, } - // z-packing compile + // z-packing compile; it imposes the correct accumulation over Numerator and Denominator. zC.Compile(comp) // prover step; Z assignments zAssignmentTask := lookup.ZAssignmentTask(*zC) comp.SubProvers.AppendToInner(zC.Round, func(run *wizard.ProverRuntime) { zAssignmentTask.Run(run) }) + // collect all the zOpening for all the z columns va.ZOpenings = append(va.ZOpenings, zC.ZOpenings...) } - va.LogDeriveSumID = qName + // verifer step + va.LogDerivSumID = qName lastRound := comp.NumRounds() - 1 comp.RegisterVerifierAction(lastRound, &va) } @@ -55,12 +58,10 @@ func CompileLogDerivSum(comp *wizard.CompiledIOP) { } type FinalEvaluationCheck struct { - // the name of a lookupTable in the pack, this can help for debugging. - Name string // ZOpenings lists all the openings of all the zCtx ZOpenings []query.LocalOpening // query ID - LogDeriveSumID ifaces.QueryID + LogDerivSumID ifaces.QueryID } // Run implements the [wizard.VerifierAction] @@ -74,9 +75,9 @@ func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { zSum.Add(&zSum, &temp) } - claimedSum := run.GetLogDerivSumParams(f.LogDeriveSumID).Sum + claimedSum := run.GetLogDerivSumParams(f.LogDerivSumID).Sum if zSum != claimedSum { - return fmt.Errorf("log-derivate lookup, the final evaluation check failed for %v,", f.Name) + return fmt.Errorf("log-derivate-sum, the final evaluation check failed for %v,", f.LogDerivSumID) } return nil @@ -85,7 +86,7 @@ func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { // RunGnark implements the [wizard.VerifierAction] func (f *FinalEvaluationCheck) RunGnark(api frontend.API, run *wizard.WizardVerifierCircuit) { - claimedSum := run.GetLogDerivSumParams(f.LogDeriveSumID) + claimedSum := run.GetLogDerivSumParams(f.LogDerivSumID).Sum // SigmaSKSum stores the sum of the ending values of the SigmaSs as queried // in the protocol via the zSum := frontend.Variable(field.Zero()) diff --git a/prover/protocol/compiler/logderivative_sum.go/logderivsum_test.go b/prover/protocol/compiler/logderivative_sum.go/logderivsum_test.go new file mode 100644 index 000000000..854b225a2 --- /dev/null +++ b/prover/protocol/compiler/logderivative_sum.go/logderivsum_test.go @@ -0,0 +1,75 @@ +package logderiv_test + +import ( + "testing" + + "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" + "github.com/consensys/linea-monorepo/prover/maths/field" + "github.com/consensys/linea-monorepo/prover/protocol/compiler/dummy" + logderiv "github.com/consensys/linea-monorepo/prover/protocol/compiler/logderivative_sum.go" + "github.com/consensys/linea-monorepo/prover/protocol/ifaces" + "github.com/consensys/linea-monorepo/prover/protocol/query" + "github.com/consensys/linea-monorepo/prover/protocol/wizard" + "github.com/consensys/linea-monorepo/prover/symbolic" + "github.com/stretchr/testify/require" +) + +// It tests that the given expression for the LogDerivativeSum adds up to the given parameter. +func TestLogDerivSum(t *testing.T) { + + define := func(b *wizard.Builder) { + var ( + comp = b.CompiledIOP + ) + + p0 := b.RegisterCommit("Num_0", 4) + p1 := b.RegisterCommit("Num_1", 4) + p2 := b.RegisterCommit("Num_2", 4) + + q0 := b.RegisterCommit("Den_0", 4) + q1 := b.RegisterCommit("Den_1", 4) + q2 := b.RegisterCommit("Den_2", 4) + + numerators := []*symbolic.Expression{ + symbolic.Mul(p0, -1), + ifaces.ColumnAsVariable(p1), + symbolic.Mul(p2, p0, 2), + } + + denominators := []*symbolic.Expression{ + ifaces.ColumnAsVariable(q0), + ifaces.ColumnAsVariable(q1), + ifaces.ColumnAsVariable(q2), + } + + key := [2]int{0, 4} + zCat1 := map[[2]int]*query.LogDerivativeSumInput{} + zCat1[key] = &query.LogDerivativeSumInput{ + Round: 0, + Size: 4, + Numerator: numerators, + Denominator: denominators, + } + comp.InsertLogDerivativeSum(0, "LogDerivSum_Test", zCat1) + + } + + prover := func(run *wizard.ProverRuntime) { + + run.AssignColumn("Num_0", smartvectors.ForTest(1, 1, 1, 1)) + run.AssignColumn("Num_1", smartvectors.ForTest(2, 3, 7, 9)) + run.AssignColumn("Num_2", smartvectors.ForTest(5, 6, 1, 1)) + + run.AssignColumn("Den_0", smartvectors.ForTest(1, 1, 1, 1)) + run.AssignColumn("Den_1", smartvectors.ForTest(2, 3, 7, 9)) + run.AssignColumn("Den_2", smartvectors.ForTest(5, 6, 1, 1)) + + run.AssignLogDerivSum("LogDerivSum_Test", field.NewElement(8)) + + } + + compiled := wizard.Compile(define, logderiv.CompileLogDerivSum, dummy.Compile) + proof := wizard.Prove(compiled, prover) + valid := wizard.Verify(compiled, proof) + require.NoError(t, valid) +} diff --git a/prover/protocol/query/gnark_params.go b/prover/protocol/query/gnark_params.go index fc2ddabbf..903102d8e 100644 --- a/prover/protocol/query/gnark_params.go +++ b/prover/protocol/query/gnark_params.go @@ -16,11 +16,11 @@ func (p LocalOpeningParams) GnarkAssign() GnarkLocalOpeningParams { } type GnarkLogDerivSumParams struct { - Y frontend.Variable + Sum frontend.Variable } func (p LogDerivSumParams) GnarkAssign() GnarkLogDerivSumParams { - return GnarkLogDerivSumParams{Y: p.Sum} + return GnarkLogDerivSumParams{Sum: p.Sum} } // A gnark circuit version of InnerProductParams @@ -64,7 +64,7 @@ func (p GnarkLocalOpeningParams) UpdateFS(fs *fiatshamir.GnarkFiatShamir) { // Update the fiat-shamir state with the the present parameters func (p GnarkLogDerivSumParams) UpdateFS(fs *fiatshamir.GnarkFiatShamir) { - fs.Update(p.Y) + fs.Update(p.Sum) } // Update the fiat-shamir state with the the present parameters diff --git a/prover/protocol/wizard/gnark_verifier.go b/prover/protocol/wizard/gnark_verifier.go index efe06be28..10d035cb2 100644 --- a/prover/protocol/wizard/gnark_verifier.go +++ b/prover/protocol/wizard/gnark_verifier.go @@ -319,9 +319,9 @@ func (c *WizardVerifierCircuit) GetLocalPointEvalParams(name ifaces.QueryID) que // GetLogDerivSumParams returns the parameters for the requested // [query.LogDerivativeSum] query. Its work mirrors the function // [VerifierRuntime.GetLogDerivSumParams] -func (c *WizardVerifierCircuit) GetLogDerivSumParams(name ifaces.QueryID) query.GnarkLocalOpeningParams { - qID := c.localOpeningIDs.MustGet(name) - return c.LocalOpeningParams[qID] +func (c *WizardVerifierCircuit) GetLogDerivSumParams(name ifaces.QueryID) query.GnarkLogDerivSumParams { + qID := c.logDerivSumIDs.MustGet(name) + return c.LogDerivSumParams[qID] } // GetColumns returns the gnark assignment of a column in a gnark circuit. It From 0f0fb0c45cac6dbb56f3a71daaa4fc534abf95a5 Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Tue, 7 Jan 2025 10:47:16 +0100 Subject: [PATCH 5/8] removed the changes unrelavant to the PR --- prover/protocol/distributed/preparation.go | 158 --------------------- 1 file changed, 158 deletions(-) diff --git a/prover/protocol/distributed/preparation.go b/prover/protocol/distributed/preparation.go index 16662758b..e70526eac 100644 --- a/prover/protocol/distributed/preparation.go +++ b/prover/protocol/distributed/preparation.go @@ -1,20 +1,14 @@ package distributed import ( - sv "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" - "github.com/consensys/linea-monorepo/prover/maths/common/vector" - "github.com/consensys/linea-monorepo/prover/maths/field" - "github.com/consensys/linea-monorepo/prover/protocol/column" "github.com/consensys/linea-monorepo/prover/protocol/compiler/innerproduct" "github.com/consensys/linea-monorepo/prover/protocol/compiler/lookup" "github.com/consensys/linea-monorepo/prover/protocol/compiler/mimc" "github.com/consensys/linea-monorepo/prover/protocol/compiler/specialqueries" - "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/query" "github.com/consensys/linea-monorepo/prover/protocol/wizard" "github.com/consensys/linea-monorepo/prover/protocol/wizardutils" "github.com/consensys/linea-monorepo/prover/symbolic" - "github.com/consensys/linea-monorepo/prover/utils" ) // prepare reduces any query to LPP or GL. @@ -131,155 +125,3 @@ func PushToZCatalog(stc lookup.SingleTableCtx, zCatalog map[[2]int]*query.LogDer zCtxEntry.Denominator = append(zCtxEntry.Denominator, symbolic.Add(stc.Gamma, stc.S[table])) } } - -// PrepareMAssignment outputs a list mapping the ID of a M column to its witness. -func PrepareMAssignment(a lookup.MAssignmentTask, run ifaces.Runtime) map[ifaces.ColID]*sv.Regular { - - var ( - // isMultiColumn flags whether the table have multiple column and - // whether the "collapsing" trick is needed. - isMultiColumn = len(a.T[0]) > 1 - - // tCollapsed contains either the assignment of T if the table is a - // single column (e.g. isMultiColumn=false) or its collapsed version - // otherwise. - tCollapsed = make([]sv.SmartVector, len(a.T)) - - // sCollapsed contains either the assignment of the Ss if the table is a - // single column (e.g. isMultiColumn=false) or their collapsed version - // otherwise. - sCollapsed = make([]sv.SmartVector, len(a.S)) - - // fragmentUnionSize contains the total number of rows contained in all - // the fragments of T combined. - fragmentUnionSize int - ) - - if !isMultiColumn { - for frag := range a.T { - tCollapsed[frag] = a.T[frag][0].GetColAssignment(run) - fragmentUnionSize += a.T[frag][0].Size() - } - - for i := range a.S { - sCollapsed[i] = a.S[i][0].GetColAssignment(run) - } - } - - if isMultiColumn { - // collapsingRandomness is the randomness used in the collapsing trick. - // It is sampled via `crypto/rand` internally to ensure it cannot be - // predicted ahead of time by an adversary. - var collapsingRandomness field.Element - if _, err := collapsingRandomness.SetRandom(); err != nil { - utils.Panic("could not sample the collapsing randomness: %v", err.Error()) - } - - for frag := range a.T { - tCollapsed[frag] = column.RandLinCombColAssignment(run, collapsingRandomness, a.T[frag]) - } - - for i := range a.S { - sCollapsed[i] = column.RandLinCombColAssignment(run, collapsingRandomness, a.S[i]) - } - } - - var ( - // m is associated with tCollapsed - // m stores the assignment to the column M as we build it. - m = make([][]field.Element, len(a.T)) - - // mapm collects the entries in the inclusion set to their positions - // in tCollapsed. If T contains duplicates, the last position is the - // one that is kept in mapM. - // - // It is used to let us know where an entry of S appears in T. The stored - // 2-uple of integers indicate [fragment, row] - mapM = make(map[field.Element][2]int, fragmentUnionSize) - - // one stores a reference to the field element equals to 1 for - // convenience so that we can use pointer on it directly. - one = field.One() - ) - - // This loops initializes mapM so that it tracks to the positions of the - // entries of T. It also preinitializes the values of ms - for frag := range a.T { - m[frag] = make([]field.Element, tCollapsed[frag].Len()) - for k := 0; k < tCollapsed[frag].Len(); k++ { - mapM[tCollapsed[frag].Get(k)] = [2]int{frag, k} - } - } - - // This loops counts all the occurences of the rows of T within S and store - // them into S. - for i := range sCollapsed { - - var ( - hasFilter = a.SFilter[i] != nil - filter []field.Element - ) - - if hasFilter { - filter = a.SFilter[i].GetColAssignment(run).IntoRegVecSaveAlloc() - } - - for k := 0; k < sCollapsed[i].Len(); k++ { - - if hasFilter && filter[k].IsZero() { - continue - } - - if hasFilter && !filter[k].IsOne() { - utils.Panic( - "the filter column `%v` has a non-binary value at position `%v`: (%v)", - a.SFilter[i].GetColID(), - k, - filter[k].String(), - ) - } - - var ( - // v stores the entry of S that we are examining and looking for - // in the look up table. - v = sCollapsed[i].Get(k) - - // posInM stores the position of `v` in the look-up table - posInM, ok = mapM[v] - ) - - if !ok { - tableRow := make([]field.Element, len(a.S[i])) - for j := range tableRow { - tableRow[j] = a.S[i][j].GetColAssignmentAt(run, k) - } - utils.Panic( - "entry %v of the table %v is not included in the table. tableRow=%v", - k, lookup.NameTable([][]ifaces.Column{a.S[i]}), vector.Prettify(tableRow), - ) - } - - mFrag, posInFragM := posInM[0], posInM[1] - m[mFrag][posInFragM].Add(&m[mFrag][posInFragM], &one) - } - - } - - for frag := range m { - mList[a.M[frag].GetColID()] = sv.NewRegular(m[frag]) - } - return mList - /* - a more professional way: - Pass all the prover message columns as part of the proof - - messages := collection.NewMapping[ifaces.ColID, ifaces.ColAssignment]() - - for _, name := range runtime.Spec.Columns.AllKeysProof() { - messageValue := runtime.Columns.MustGet(name) - messages.InsertNew(name, messageValue) - } - */ -} - -var mList map[ifaces.ColID]*sv.Regular From d61c3f5b5478e4bd8ef382230cc5965661969228 Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Tue, 7 Jan 2025 11:35:09 +0100 Subject: [PATCH 6/8] minor; clarifing the panic error --- prover/protocol/compiler/logderivative_sum.go/compile.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prover/protocol/compiler/logderivative_sum.go/compile.go b/prover/protocol/compiler/logderivative_sum.go/compile.go index 04fc06692..edac1f402 100644 --- a/prover/protocol/compiler/logderivative_sum.go/compile.go +++ b/prover/protocol/compiler/logderivative_sum.go/compile.go @@ -77,7 +77,9 @@ func (f *FinalEvaluationCheck) Run(run *wizard.VerifierRuntime) error { claimedSum := run.GetLogDerivSumParams(f.LogDerivSumID).Sum if zSum != claimedSum { - return fmt.Errorf("log-derivate-sum, the final evaluation check failed for %v,", f.LogDerivSumID) + return fmt.Errorf("log-derivate-sum; the final evaluation check failed for %v\n"+ + "given %v but calculated %v,", + f.LogDerivSumID, claimedSum.String(), zSum.String()) } return nil From c62258c63c17816c220a18c1d9508c7de12cc480 Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Tue, 7 Jan 2025 11:36:51 +0100 Subject: [PATCH 7/8] minor; changing the file name --- .../{logderivative_sum.go => logderivativesum}/compile.go | 0 .../logderivsum_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename prover/protocol/compiler/{logderivative_sum.go => logderivativesum}/compile.go (100%) rename prover/protocol/compiler/{logderivative_sum.go => logderivativesum}/logderivsum_test.go (100%) diff --git a/prover/protocol/compiler/logderivative_sum.go/compile.go b/prover/protocol/compiler/logderivativesum/compile.go similarity index 100% rename from prover/protocol/compiler/logderivative_sum.go/compile.go rename to prover/protocol/compiler/logderivativesum/compile.go diff --git a/prover/protocol/compiler/logderivative_sum.go/logderivsum_test.go b/prover/protocol/compiler/logderivativesum/logderivsum_test.go similarity index 100% rename from prover/protocol/compiler/logderivative_sum.go/logderivsum_test.go rename to prover/protocol/compiler/logderivativesum/logderivsum_test.go From 239bffcb67eccd4ed50df9b2b3b2969fc99937d0 Mon Sep 17 00:00:00 2001 From: Soleimani193 Date: Tue, 7 Jan 2025 12:11:55 +0100 Subject: [PATCH 8/8] minor typo --- prover/protocol/compiler/logderivativesum/logderivsum_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prover/protocol/compiler/logderivativesum/logderivsum_test.go b/prover/protocol/compiler/logderivativesum/logderivsum_test.go index 854b225a2..0bcf350da 100644 --- a/prover/protocol/compiler/logderivativesum/logderivsum_test.go +++ b/prover/protocol/compiler/logderivativesum/logderivsum_test.go @@ -6,7 +6,7 @@ import ( "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/compiler/dummy" - logderiv "github.com/consensys/linea-monorepo/prover/protocol/compiler/logderivative_sum.go" + logderiv "github.com/consensys/linea-monorepo/prover/protocol/compiler/logderivativesum" "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/query" "github.com/consensys/linea-monorepo/prover/protocol/wizard"