Prover: richer exit code to better detect completeness issues (#978)

* feat(exit): make sure that keccak uses 77 when overflowing and not a panic message

* feat(exit): makes PadAssign return a 77 when vector builder overflows

* feat(exit): adds a toggle mechanism for the exiting strategy

* feat(unsatisfied): adds exiting when encountering an unsatisfied constraint

* adds the toggle for the exit when finding unsatisfied constraints

* feat(77): uses the 77 exit code to tell when we have too many merkle proofs

* fix log for modexp
This commit is contained in:
AlexandreBelling
2025-05-13 22:46:05 +02:00
committed by GitHub
parent 2ea227d2d5
commit 3bf08c9f18
13 changed files with 95 additions and 20 deletions

View File

@@ -11,6 +11,7 @@ import (
"github.com/consensys/linea-monorepo/prover/config"
public_input "github.com/consensys/linea-monorepo/prover/public-input"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/consensys/linea-monorepo/prover/utils/profiling"
"github.com/consensys/linea-monorepo/prover/zkevm"
"github.com/sirupsen/logrus"
@@ -26,6 +27,10 @@ func Prove(cfg *config.Config, req *Request, large bool) (*Response, error) {
// Set MonitorParams before any proving happens
profiling.SetMonitorParams(cfg)
// This instructs the [exit] package to actually exit when [OnLimitOverflow]
// or [OnSatisfiedConstraints] are called.
exit.ActivateExitOnIssue()
var resp Response
// TODO @gbotrel wrap profiling in the caller; so that we can properly return errors
@@ -146,7 +151,8 @@ func mustProveAndPass(
logrus.Info("Sanity-checking the inner-proof")
if err := fullZkEvm.VerifyInner(proof); err != nil {
utils.Panic("The prover did not pass: %v", err)
logrus.Errorf("The sanity-check of the inner-proof did not pass: %v", err)
exit.OnUnsatisfiedConstraints()
}
// wait for setup to be loaded

View File

@@ -11,7 +11,9 @@ import (
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
"github.com/consensys/linea-monorepo/prover/protocol/wizardutils"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/consensys/linea-monorepo/prover/utils/parallel"
"github.com/sirupsen/logrus"
)
// proverTaskAtRound implements the [wizard.ProverAction] interface. It gathers
@@ -257,12 +259,16 @@ func (a mAssignmentTask) run(run *wizard.ProverRuntime) {
}
if hasFilter && !filter[k].IsOne() {
utils.Panic(
logrus.Errorf(
"the filter column `%v` has a non-binary value at position `%v`: (%v)",
a.SFilter[i].GetColID(),
k,
filter[k].String(),
)
// Even if this is unconstrained, this is still worth interrupting the
// prover because it "should" be a binary column.
exit.OnUnsatisfiedConstraints()
}
var (
@@ -279,10 +285,12 @@ func (a mAssignmentTask) run(run *wizard.ProverRuntime) {
for j := range tableRow {
tableRow[j] = a.S[i][j].GetColAssignmentAt(run, k)
}
utils.Panic(
logrus.Errorf(
"entry %v of the table %v is not included in the table. tableRow=%v",
k, nameTable([][]ifaces.Column{a.S[i]}), vector.Prettify(tableRow),
)
exit.OnUnsatisfiedConstraints()
}
mFrag, posInFragM := posInM[0], posInM[1]

View File

@@ -112,7 +112,7 @@ func (ctx localOpeningCtx) verifier(assi *wizard.VerifierRuntime) error {
}
if len(ys) != len(newParams.Ys) {
utils.Panic("the ys do not have the same length")
return fmt.Errorf("the ys do not have the same length")
}
errMsg := "fixed point compiler verifier failed\n"

View File

@@ -2,12 +2,14 @@ package univariates
import (
"fmt"
ppool "github.com/consensys/linea-monorepo/prover/utils/parallel/pool"
"math/big"
"reflect"
"runtime"
"sync"
"github.com/consensys/linea-monorepo/prover/utils/exit"
ppool "github.com/consensys/linea-monorepo/prover/utils/parallel/pool"
"github.com/consensys/gnark/frontend"
"github.com/sirupsen/logrus"
@@ -322,7 +324,8 @@ func (ctx mptsCtx) accumulateQuotients(run *wizard.ProverRuntime) {
panicMsg += fmt.Sprintf("\t\tfor %v, P(x) = %v\n", q.Pols[i].GetColID(), params.Ys[i].String())
}
utils.Panic("%vremainder was %v (while reducing %v from query %v) \n", panicMsg, rem.String(), polHandle.GetColID(), ctx.hs[hpos])
logrus.Errorf("%vremainder was %v (while reducing %v from query %v) \n", panicMsg, rem.String(), polHandle.GetColID(), ctx.hs[hpos])
exit.OnUnsatisfiedConstraints()
}
}

View File

@@ -2,7 +2,6 @@ package plonk
import (
"fmt"
"os"
"sync"
"github.com/consensys/gnark-crypto/ecc"
@@ -17,6 +16,7 @@ import (
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
"github.com/consensys/linea-monorepo/prover/symbolic"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/sirupsen/logrus"
"golang.org/x/net/context"
"golang.org/x/sync/errgroup"
@@ -96,7 +96,7 @@ func (ci *CircuitAlignmentInput) prepareWitnesses(run *wizard.ProverRuntime) {
// Don't use the fatal level here because we want to control the exit code
// to be 77.
logrus.Errorf("fatal=%v", err)
os.Exit(77)
exit.OnLimitOverflow()
}
if ci.InputFiller == nil {

46
prover/utils/exit/exit.go Normal file
View File

@@ -0,0 +1,46 @@
package exit
import (
"os"
"runtime/debug"
)
var (
activateExitOnIssue bool
)
// ActivateExitOnIssue tells the program to actually exit when [OnLimitOverflow]
// or [OnSatisfiedConstraints] are called. This has to be manually called at the
// beginning of the program if we want the behavior to take place. This is
// to avoid having it running in the tests.
func ActivateExitOnIssue() {
activateExitOnIssue = true
}
const (
limitOverflowExitCode = 77
unsatisfiedConstraintsExitCode = 78
)
// This function will exit the program with the exit code [limitOverflowExitCode]
// but only if the activateExitOnIssue flag is set to true. Otherwise, it will
// just panic.
func OnLimitOverflow() {
debug.PrintStack()
if !activateExitOnIssue {
panic("limit overflow")
}
os.Exit(limitOverflowExitCode)
}
func OnUnsatisfiedConstraints() {
debug.PrintStack()
if !activateExitOnIssue {
panic("unsatisfied constraints")
}
os.Exit(unsatisfiedConstraintsExitCode)
}

View File

@@ -74,7 +74,7 @@ func (a *Arithmetization) Assign(run *wizard.ProverRuntime, traceFile string) {
// Performs a compatibility check by comparing the constraints
// commit of zkevm.bin with the constraints commit of the trace file.
// Panics if an incompatibility is detected.
if *a.Settings.IgnoreCompatibilityCheck == false {
if !*a.Settings.IgnoreCompatibilityCheck {
var errors []string
zkevmBinCommit, ok := a.Metadata.String("commit")

View File

@@ -3,7 +3,6 @@ package arithmetization
import (
"errors"
"fmt"
"os"
"github.com/consensys/go-corset/pkg/air"
"github.com/consensys/go-corset/pkg/trace"
@@ -12,6 +11,7 @@ import (
"github.com/consensys/linea-monorepo/prover/maths/field"
"github.com/consensys/linea-monorepo/prover/protocol/ifaces"
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/sirupsen/logrus"
)
@@ -48,7 +48,7 @@ func AssignFromLtTraces(run *wizard.ProverRuntime, schema *air.Schema, expTraces
if err77 != nil {
logrus.Errorf("Error code 77 %v", err77)
os.Exit(TraceOverflowExitCode)
exit.OnLimitOverflow()
}
for id := uint(0); id < numCols; id++ {

View File

@@ -16,8 +16,6 @@ import (
"github.com/consensys/go-corset/pkg/util/collection/typed"
)
const TraceOverflowExitCode = 77
// Embed the whole constraint system at compile time, so no
// more need to keep it in sync
//

View File

@@ -6,7 +6,9 @@ import (
"github.com/consensys/linea-monorepo/prover/protocol/ifaces"
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/consensys/linea-monorepo/prover/utils/types"
"github.com/sirupsen/logrus"
)
// VectorBuilder is a convenience structure to assign columns by appending
@@ -153,6 +155,13 @@ func (vb *VectorBuilder) PushAddr(addr types.EthAddress) {
// PadAndAssign pads and assign the column built by `vb` using `v` as padding
// value and assigning into `run`.
func (vb *VectorBuilder) PadAndAssign(run *wizard.ProverRuntime, v ...field.Element) {
if len(vb.slice) > vb.column.Size() {
logrus.Errorf("the slice size %v is larger than the column size %v", len(vb.slice), vb.column.Size())
// We print the stack to help debugging
exit.OnLimitOverflow()
}
paddingValue := field.Zero()
if len(v) > 0 {
paddingValue = v[0]

View File

@@ -11,7 +11,9 @@ import (
"github.com/consensys/linea-monorepo/prover/protocol/ifaces"
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/consensys/linea-monorepo/prover/utils/parallel"
"github.com/sirupsen/logrus"
)
const (
@@ -127,7 +129,8 @@ func (mod *Module) Assign(
// If the number of keccakf constraints is larger than what the module
// is sized for, then, we cannot prove everything.
if numKeccakf > mod.MaxNumKeccakf {
utils.Panic("Too many keccakf %v > %v", numKeccakf, mod.MaxNumKeccakf)
logrus.Errorf("Too many keccakf %v > %v", numKeccakf, mod.MaxNumKeccakf)
exit.OnLimitOverflow()
}
lu := mod.lookups

View File

@@ -1,11 +1,10 @@
package modexp
import (
"os"
"github.com/consensys/linea-monorepo/prover/maths/field"
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/consensys/linea-monorepo/prover/zkevm/prover/common"
"github.com/sirupsen/logrus"
)
@@ -88,12 +87,12 @@ func (mod *Module) Assign(run *wizard.ProverRuntime) {
if modexpCountSmall > mod.MaxNb256BitsInstances {
logrus.Errorf("limit overflow: the modexp (256 bits) count is %v and the limit is %v\n", modexpCountSmall, mod.MaxNb256BitsInstances)
os.Exit(77)
exit.OnLimitOverflow()
}
if modexpCountLarge > mod.MaxNb4096BitsInstances {
logrus.Errorf("limit overflow: the modexp (4096 bits) count is %v and the limit is %v\n", modexpCountSmall, mod.MaxNb4096BitsInstances)
os.Exit(77)
logrus.Errorf("limit overflow: the modexp (4096 bits) count is %v and the limit is %v\n", modexpCountLarge, mod.MaxNb4096BitsInstances)
exit.OnLimitOverflow()
}
builder.isActive.PadAndAssign(run, field.Zero())

View File

@@ -12,7 +12,9 @@ import (
"github.com/consensys/linea-monorepo/prover/protocol/dedicated/merkle"
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/exit"
"github.com/consensys/linea-monorepo/prover/utils/types"
"github.com/sirupsen/logrus"
)
// leafOpenings represents the structure for leaf openings
@@ -207,7 +209,8 @@ func (am *Module) Assign(
// Sanity check on the size
if len(builder.leaves) > am.MaxNumProofs {
utils.Panic("We have registered %v proofs which is more than the maximum number of proofs %v", len(builder.leaves), am.MaxNumProofs)
logrus.Errorf("We have registered %v proofs which is more than the maximum number of proofs %v", len(builder.leaves), am.MaxNumProofs)
exit.OnLimitOverflow()
}
// Assignments of columns