Files
linea-monorepo/prover/backend/execution/prove.go
David Pearce bf71b6b5ca Prover: compatibility check between zkevmbin and lt trace file (#745)
* update `go-corset` to `v0.9.4`

* feat: add binfile / tracefile compatibility check

This adds a compatibility check between the zkevm.bin file and the lt
trace file.  The compatibility check extracts the constraints commit
used to generate the respective asset, and ensures a match.  If not, the
code panics with an error.  Likewise, if the metadata is missing then
code will panic with an error.

* support "relaxed mode"

This intention here is to enable the strong compatibility check to be
disabled.  It seems sensible to have an option to turn it off, and a
flag is added to the `bin/checker` to disable it.

* remove file-based constraints version check

* update to later version of `go-corset`

In order to allow embedded line count information (as requested
separately from this PR), go-corset now uses a structured form of
metadata.  This simply updates this PR to use the revised API.

* rename "RelaxedMode" => "IgnoreCompabitilityCheck"

This simply renames the "relaxed mode" to something more direct, namely
"IgnoreCompatiblityCheck" which does what it says on the tin.

* update `go-corset` to v1.0.0

* add IgnoreCompatibilityCheck option to prover config

* remove unnecessary variable

* Update compatibility check to fail early on incompatibility

* add log when IgnoreCompatibilityCheck is enabled

---------

Co-authored-by: gusiri <dreamerty@postech.ac.kr>
2025-03-07 08:45:54 +09:00

186 lines
5.8 KiB
Go

package execution
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/linea-monorepo/prover/circuits"
"github.com/consensys/linea-monorepo/prover/circuits/dummy"
"github.com/consensys/linea-monorepo/prover/circuits/execution"
"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/profiling"
"github.com/consensys/linea-monorepo/prover/zkevm"
"github.com/sirupsen/logrus"
)
type Witness struct {
FuncInp *public_input.Execution
ZkEVM *zkevm.Witness
}
func Prove(cfg *config.Config, req *Request, large bool) (*Response, error) {
traces := &cfg.TracesLimits
if large {
traces = &cfg.TracesLimitsLarge
}
var resp Response
// TODO @gbotrel wrap profiling in the caller; so that we can properly return errors
profiling.ProfileTrace("execution",
cfg.Debug.Profiling,
cfg.Debug.Tracing,
func() {
// Compute the prover's output.
// WARN: CraftProverOutput calls functions that can panic.
out := CraftProverOutput(cfg, req)
if cfg.Execution.ProverMode != config.ProverModeProofless {
// Development, Partial, Full or Full-large Mode
// WARN:
// - MustProveAndPass can panic
// - Execution prover calls function that can panic
// - NewFromString can panic
out.Proof, out.VerifyingKeyShaSum = mustProveAndPass(
cfg,
traces,
NewWitness(cfg, req, &out),
)
out.Version = cfg.Version
out.ProverMode = cfg.Execution.ProverMode
out.VerifierIndex = uint(cfg.Aggregation.VerifierID) // TODO @gbotrel revisit
} else {
// Proofless Mode
// task.ProverConfig.Mode() == config.ProverProofless
logrus.Infof("Running the prover in proofless mode")
out.Version = cfg.Version
out.ProverMode = config.ProverModeProofless
}
resp = out
})
return &resp, nil
}
// mustProveAndPass the prover (in the void). Does not takes a
// prover-step function performing the assignment but a function
// returning such a function. This is important to avoid side-effects
// when calling it twice.
func mustProveAndPass(
cfg *config.Config,
traces *config.TracesLimits,
w *Witness,
) (proofHexString string, vkeyShaSum string) {
switch cfg.Execution.ProverMode {
case config.ProverModeDev, config.ProverModePartial:
if cfg.Execution.ProverMode == config.ProverModePartial {
logrus.Info("Running the PARTIAL prover")
// And run the partial-prover with only the main steps. The generated
// proof is sanity-checked to ensure that the prover never outputs
// invalid proofs.
partial := zkevm.FullZkEVMCheckOnly(traces, cfg)
proof := partial.ProveInner(w.ZkEVM)
if err := partial.VerifyInner(proof); err != nil {
utils.Panic("The prover did not pass: %v", err)
}
}
srsProvider, err := circuits.NewSRSStore(cfg.PathForSRS())
if err != nil {
utils.Panic(err.Error())
}
setup, err := dummy.MakeUnsafeSetup(srsProvider, circuits.MockCircuitIDExecution, ecc.BLS12_377.ScalarField())
if err != nil {
utils.Panic(err.Error())
}
return dummy.MakeProof(&setup, w.FuncInp.SumAsField(), circuits.MockCircuitIDExecution), setup.VerifyingKeyDigest()
case config.ProverModeFull:
logrus.Info("Running the FULL prover")
// Run the full prover to obtain the intermediate proof
logrus.Info("Get Full IOP")
fullZkEvm := zkevm.FullZkEvm(traces, cfg)
var (
setup circuits.Setup
errSetup error
chSetupDone = make(chan struct{})
)
go func() {
setup, errSetup = circuits.LoadSetup(cfg, circuits.ExecutionCircuitID)
close(chSetupDone)
}()
// Generates the inner-proof and sanity-check it so that we ensure that
// the prover nevers outputs invalid proofs.
proof := fullZkEvm.ProveInner(w.ZkEVM)
logrus.Info("Sanity-checking the inner-proof")
if err := fullZkEvm.VerifyInner(proof); err != nil {
utils.Panic("The prover did not pass: %v", err)
}
// wait for setup to be loaded
<-chSetupDone
if errSetup != nil {
utils.Panic("could not load setup: %v", errSetup)
}
// ensure the checksum for the traces in the setup matches the one in the config
setupCfgChecksum, err := setup.Manifest.GetString("cfg_checksum")
if err != nil {
utils.Panic("could not get the traces checksum from the setup manifest: %v", err)
}
if setupCfgChecksum != traces.Checksum() {
// This check is failing on prod but works locally.
// @alex: since this is a setup-related constraint, it would likely be
// more interesting to directly include that information in the setup
// instead of the config. That way we are guaranteed to not pass the
// wrong value at runtime.
utils.Panic("traces checksum in the setup manifest does not match the one in the config")
}
// TODO: implements the collection of the functional inputs from the prover response
return execution.MakeProof(traces, setup, fullZkEvm.WizardIOP, proof, *w.FuncInp), setup.VerifyingKeyDigest()
case config.ProverModeBench:
// Run the full prover to obtain the intermediate proof
logrus.Info("Get Full IOP")
fullZkEvm := zkevm.FullZkEvm(traces, cfg)
// Generates the inner-proof and sanity-check it so that we ensure that
// the prover nevers outputs invalid proofs.
proof := fullZkEvm.ProveInner(w.ZkEVM)
logrus.Info("Sanity-checking the inner-proof")
if err := fullZkEvm.VerifyInner(proof); err != nil {
utils.Panic("The prover did not pass: %v", err)
}
return "", ""
case config.ProverModeCheckOnly:
fullZkEvm := zkevm.FullZkEVMCheckOnly(traces, cfg)
// this will panic to alert errors, so there is no need to handle or
// sanity-check anything.
logrus.Infof("Prover starting the prover")
_ = fullZkEvm.ProveInner(w.ZkEVM)
logrus.Infof("Prover checks passed")
return "", ""
default:
panic("not implemented")
}
}