From 7bd6f77a88a52bcf895c0303f5f6456e0ee54e7f Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 4 May 2026 21:33:55 +0000 Subject: [PATCH 01/44] feat: add internal log/slog backed logger --- internal/logger/logger.go | 141 +++++++++++++++++++++++ internal/logger/logger_test.go | 203 +++++++++++++++++++++++++++++++++ 2 files changed, 344 insertions(+) create mode 100644 internal/logger/logger.go create mode 100644 internal/logger/logger_test.go diff --git a/internal/logger/logger.go b/internal/logger/logger.go new file mode 100644 index 0000000000..98b9869509 --- /dev/null +++ b/internal/logger/logger.go @@ -0,0 +1,141 @@ +// Package logger provides gnark's internal slog logger. +package logger + +import ( + "context" + "io" + "log/slog" + "os" + "runtime" + runtimedebug "runtime/debug" + "strings" + "sync" + + "github.com/consensys/gnark" + "github.com/consensys/gnark-crypto/utils/cpu" + "github.com/consensys/gnark/debug" +) + +const ( + // EnvLevel is the environment variable used to configure the default logger. + EnvLevel = "GNARK_LOG_LEVEL" + + LevelTrace slog.Level = -8 + + LevelDisabled slog.Level = 1<<31 - 1 +) + +var ( + defaultOnce = new(sync.Once) + defaultLogger *slog.Logger + defaultOutput io.Writer = os.Stdout +) + +// Logger returns gnark's default internal logger. +func Logger() *slog.Logger { + defaultOnce.Do(func() { + level := levelFromEnv(debug.Debug) + if level == LevelDisabled { + defaultLogger = slog.New(newHandler(io.Discard, level)) + return + } + defaultLogger = slog.New(newHandler(defaultOutput, level)) + logDebugRuntimeInfo(defaultLogger) + }) + return defaultLogger +} + +func newHandler(w io.Writer, level slog.Level) slog.Handler { + return slog.NewTextHandler(w, &slog.HandlerOptions{ + // We want to include the source for trace logs, but not for higher + // levels, to avoid the overhead of getting the caller info when it's + // not needed. + AddSource: level <= LevelTrace, + Level: level, + // LevelTrace is not a standard slog level, so we need to replace it + // with a string for the text handler. + ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { + if a.Key == slog.LevelKey && a.Value.Kind() == slog.KindAny { + if level, ok := a.Value.Any().(slog.Level); ok && level == LevelTrace { + a.Value = slog.StringValue("TRACE") + } + } + return a + }, + }) +} + +func levelFromEnv(debugDefault bool) slog.Level { + envLevel, ok := os.LookupEnv(EnvLevel) + if !ok { + if debugDefault { + return slog.LevelDebug + } + return slog.LevelInfo + } + switch strings.ToLower(strings.TrimSpace(envLevel)) { + case "trace": + return LevelTrace + case "debug": + return slog.LevelDebug + case "", "info": + return slog.LevelInfo + case "warning", "warn": + return slog.LevelWarn + case "error": + return slog.LevelError + case "quiet", "none": + return LevelDisabled + default: + return slog.LevelInfo + } +} + +func logDebugRuntimeInfo(log *slog.Logger) { + if !log.Enabled(context.Background(), slog.LevelDebug) { + return + } + buildInfo, ok := runtimedebug.ReadBuildInfo() + if !ok { + log.LogAttrs(context.Background(), slog.LevelDebug, "runtime configuration", runtimeInfoAttrs(nil)...) + return + } + log.LogAttrs(context.Background(), slog.LevelDebug, "runtime configuration", runtimeInfoAttrs(buildInfo)...) +} + +func runtimeInfoAttrs(buildInfo *runtimedebug.BuildInfo) []slog.Attr { + attrs := []slog.Attr{ + slog.Int("gomaxprocs", runtime.GOMAXPROCS(0)), + slog.Int64("gomemlimit", runtimedebug.SetMemoryLimit(-1)), + slog.String("goarch", runtime.GOARCH), + slog.String("goos", runtime.GOOS), + slog.Bool("support_neon", cpu.SupportNEON), + slog.Bool("support_avx512", cpu.SupportAVX512), + slog.Bool("support_avx512ifma", cpu.SupportAVX512IFMA), + slog.String("gnark_version", gnark.Version.String()), + } + if runtime.GOARCH == "arm" { + attrs = append(attrs, slog.String("goarm", buildSetting(buildInfo, "GOARM"))) + } + if buildInfo != nil { + attrs = append(attrs, + slog.String("build_tags", buildSetting(buildInfo, "-tags")), + slog.String("go_build_version", buildInfo.GoVersion), + slog.String("vcs_tagged_version", buildInfo.Main.Version), + slog.String("vcs_modified", buildSetting(buildInfo, "vcs.modified")), + ) + } + return attrs +} + +func buildSetting(buildInfo *runtimedebug.BuildInfo, key string) string { + if buildInfo == nil { + return "" + } + for _, setting := range buildInfo.Settings { + if setting.Key == key { + return setting.Value + } + } + return "" +} diff --git a/internal/logger/logger_test.go b/internal/logger/logger_test.go new file mode 100644 index 0000000000..91b723d8e1 --- /dev/null +++ b/internal/logger/logger_test.go @@ -0,0 +1,203 @@ +package logger + +import ( + "bytes" + "context" + "log/slog" + "os" + "runtime" + "strings" + "sync" + "testing" + + "github.com/consensys/gnark/debug" +) + +func TestLoggerUsesInfoTextHandler(t *testing.T) { + var buf bytes.Buffer + withLoggerOutput(t, &buf) + + t.Setenv(EnvLevel, "info") + log := Logger() + + log.Debug("hidden") + log.Info("visible") + + output := buf.String() + if strings.Contains(output, "hidden") { + t.Fatal("debug log should not be emitted at the default level") + } + if !strings.Contains(output, "level=INFO") || !strings.Contains(output, "msg=visible") { + t.Fatalf("expected info text output, got %q", output) + } + if !strings.Contains(output, "time=") { + t.Fatalf("expected timestamp in text output, got %q", output) + } +} + +func TestLoggerDefaultsToDebugWithDebugBuildTag(t *testing.T) { + var buf bytes.Buffer + withLoggerOutput(t, &buf) + withUnsetenv(t, EnvLevel) + + log := Logger() + log.Debug("visible") + + output := buf.String() + if debug.Debug { + if !strings.Contains(output, "level=DEBUG") || !strings.Contains(output, "msg=visible") { + t.Fatalf("expected debug output with debug build tag, got %q", output) + } + return + } + if strings.Contains(output, "msg=visible") { + t.Fatalf("debug output should not be emitted without debug build tag, got %q", output) + } +} + +func TestEnvironmentOverridesDebugBuildTagDefault(t *testing.T) { + t.Setenv(EnvLevel, "error") + if level := levelFromEnv(true); level != slog.LevelError { + t.Fatalf("expected environment level to override debug default, got %s", level) + } +} + +func TestLoggerReadsEnvironmentLevel(t *testing.T) { + testCases := []struct { + name string + env string + level slog.Level + expected string + }{ + {name: "trace", env: "trace", level: LevelTrace, expected: "level=TRACE"}, + {name: "debug", env: "debug", level: slog.LevelDebug, expected: "level=DEBUG"}, + {name: "info", env: "info", level: slog.LevelInfo, expected: "level=INFO"}, + {name: "warning", env: "warning", level: slog.LevelWarn, expected: "level=WARN"}, + {name: "error", env: "error", level: slog.LevelError, expected: "level=ERROR"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var buf bytes.Buffer + withLoggerOutput(t, &buf) + t.Setenv(EnvLevel, tc.env) + + Logger().Log(context.Background(), tc.level, "visible") + + output := buf.String() + if !strings.Contains(output, tc.expected) || !strings.Contains(output, "msg=visible") { + t.Fatalf("expected %q output, got %q", tc.expected, output) + } + }) + } +} + +func TestLoggerQuietLevelDisablesOutput(t *testing.T) { + for _, env := range []string{"quiet", "none"} { + t.Run(env, func(t *testing.T) { + var buf bytes.Buffer + withLoggerOutput(t, &buf) + t.Setenv(EnvLevel, env) + + log := Logger() + log.Error("hidden") + log.Log(context.Background(), LevelTrace, "hidden") + + if log.Enabled(context.Background(), slog.LevelError) { + t.Fatal("quiet logger should be disabled for error logs") + } + if output := buf.String(); output != "" { + t.Fatalf("quiet logger should not emit output, got %q", output) + } + }) + } +} + +func TestLoggerDebugLevelEmitsRuntimeInfo(t *testing.T) { + var buf bytes.Buffer + withLoggerOutput(t, &buf) + t.Setenv(EnvLevel, "debug") + + Logger() + + output := buf.String() + for _, expected := range []string{ + "msg=\"runtime configuration\"", + "gomaxprocs=", + "gomemlimit=", + "build_tags=", + "goarch=", + "goos=", + "support_neon=", + "support_avx512=", + "support_avx512ifma=", + "go_build_version=", + "vcs_tagged_version=", + "vcs_modified=", + "gnark_version=", + } { + if !strings.Contains(output, expected) { + t.Fatalf("expected %q in debug runtime output, got %q", expected, output) + } + } + if runtime.GOARCH == "arm" { + if !strings.Contains(output, "goarm=") { + t.Fatalf("expected goarm in debug runtime output for arm, got %q", output) + } + } else if strings.Contains(output, "goarm=") { + t.Fatalf("did not expect goarm in debug runtime output for %s, got %q", runtime.GOARCH, output) + } +} + +func TestLoggerTraceLevelEmitsSource(t *testing.T) { + var buf bytes.Buffer + withLoggerOutput(t, &buf) + t.Setenv(EnvLevel, "trace") + + Logger().Log(context.Background(), LevelTrace, "visible") + + output := buf.String() + if !strings.Contains(output, "level=TRACE") || !strings.Contains(output, "msg=visible") { + t.Fatalf("expected trace output, got %q", output) + } + if !strings.Contains(output, "source=") { + t.Fatalf("expected source location in trace output, got %q", output) + } +} + +func withLoggerOutput(t *testing.T, w *bytes.Buffer) { + t.Helper() + + previousOutput := defaultOutput + previousLogger := defaultLogger + previousOnce := defaultOnce + defaultOutput = w + defaultLogger = nil + defaultOnce = new(sync.Once) + + t.Cleanup(func() { + defaultOutput = previousOutput + defaultLogger = previousLogger + defaultOnce = previousOnce + }) +} + +func withUnsetenv(t *testing.T, key string) { + t.Helper() + + previousValue, previousSet := os.LookupEnv(key) + if err := os.Unsetenv(key); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + var err error + if previousSet { + err = os.Setenv(key, previousValue) + } else { + err = os.Unsetenv(key) + } + if err != nil { + t.Fatal(err) + } + }) +} From f360eb58aef48929a70cd02dc41017e115492138 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 4 May 2026 21:46:51 +0000 Subject: [PATCH 02/44] feat: passthrough old logger to new logger with deprecation --- logger/logger.go | 132 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 12 deletions(-) diff --git a/logger/logger.go b/logger/logger.go index e665545655..40e6100f60 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,45 +1,153 @@ -// Package logger provides a configurable logger across gnark components +// Package logger provides a deprecated zerolog-compatible logger. // -// The root logger defined by default uses github.com/rs/zerolog with a console writer +// Deprecated: use log/slog with github.com/consensys/gnark/internal/logger +// inside gnark. This package will be removed soon. package logger import ( + "bytes" + "context" + "encoding/json" "io" - "os" + "log/slog" + "sort" + "sync" "testing" + internallogger "github.com/consensys/gnark/internal/logger" + "github.com/consensys/gnark/debug" "github.com/rs/zerolog" ) -var logger zerolog.Logger +const deprecationMessage = "github.com/consensys/gnark/logger is deprecated and will be removed soon; use log/slog instead" + +var ( + logger zerolog.Logger + deprecatedOnce sync.Once +) func init() { - output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "15:04:05"} - logger = zerolog.New(output).With().Timestamp().Logger() + logger = newSlogBackedZerolog() if !debug.Debug && testing.Testing() { logger = zerolog.Nop() } - } -// SetOutput changes the output of the global logger +// SetOutput changes the output of the global logger. +// +// Deprecated: use log/slog directly. This package will be removed soon. func SetOutput(w io.Writer) { - logger = logger.Output(w) + warnDeprecated() + logger = zerolog.New(w).Level(zerolog.TraceLevel) } -// Set allows a gnark user to overhide the global logger +// Set allows a gnark user to override the global logger. +// +// Deprecated: use log/slog directly. This package will be removed soon. func Set(l zerolog.Logger) { + warnDeprecated() logger = l } -// Disable disables logging +// Disable disables logging. +// +// Deprecated: use log/slog directly. This package will be removed soon. func Disable() { + warnDeprecated() logger = zerolog.Nop() } -// Logger returns a sublogger for a component +// Logger returns the legacy zerolog-compatible logger. +// +// Deprecated: use log/slog directly. This package will be removed soon. func Logger() zerolog.Logger { + warnDeprecated() return logger } + +func newSlogBackedZerolog() zerolog.Logger { + return zerolog.New(slogLevelWriter{}).Level(zerolog.TraceLevel) +} + +func warnDeprecated() { + if logger.GetLevel() == zerolog.Disabled { + return + } + deprecatedOnce.Do(func() { + internallogger.Logger().Warn(deprecationMessage) + }) +} + +type slogLevelWriter struct{} + +func (slogLevelWriter) Write(p []byte) (int, error) { + return slogLevelWriter{}.WriteLevel(zerolog.NoLevel, p) +} + +func (slogLevelWriter) WriteLevel(level zerolog.Level, p []byte) (int, error) { + level, msg, attrs := decodeZerologEvent(level, p) + internallogger.Logger().LogAttrs(context.Background(), slogLevel(level), msg, attrs...) + return len(p), nil +} + +func decodeZerologEvent(level zerolog.Level, p []byte) (zerolog.Level, string, []slog.Attr) { + decoder := json.NewDecoder(bytes.NewReader(p)) + decoder.UseNumber() + + var fields map[string]any + if err := decoder.Decode(&fields); err != nil { + return level, string(bytes.TrimSpace(p)), nil + } + + if level == zerolog.NoLevel { + level = zerologLevel(fields[zerolog.LevelFieldName]) + } + + msg, _ := fields[zerolog.MessageFieldName].(string) + delete(fields, zerolog.LevelFieldName) + delete(fields, zerolog.MessageFieldName) + delete(fields, zerolog.TimestampFieldName) + + keys := make([]string, 0, len(fields)) + for key := range fields { + keys = append(keys, key) + } + sort.Strings(keys) + + attrs := make([]slog.Attr, 0, len(keys)) + for _, key := range keys { + attrs = append(attrs, slog.Any(key, fields[key])) + } + return level, msg, attrs +} + +func zerologLevel(value any) zerolog.Level { + level, ok := value.(string) + if !ok { + return zerolog.InfoLevel + } + parsed, err := zerolog.ParseLevel(level) + if err != nil { + return zerolog.InfoLevel + } + return parsed +} + +func slogLevel(level zerolog.Level) slog.Level { + switch level { + case zerolog.TraceLevel: + return internallogger.LevelTrace + case zerolog.DebugLevel: + return slog.LevelDebug + case zerolog.InfoLevel, zerolog.NoLevel: + return slog.LevelInfo + case zerolog.WarnLevel: + return slog.LevelWarn + case zerolog.ErrorLevel, zerolog.FatalLevel, zerolog.PanicLevel: + return slog.LevelError + default: + return slog.LevelInfo + } +} From 77faa02688a54283d7a4982063207b5083c642c2 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 4 May 2026 21:47:46 +0000 Subject: [PATCH 03/44] docs: add log level info to README --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 50af91482e..426122689c 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,19 @@ go run ./examples/cubic To design your first circuit, follow the tutorial in [`gnark` User Documentation]. +## Logging + +`gnark` reads `GNARK_LOG_LEVEL` to configure internal logs: + +- `trace`: logs all records and includes source locations. +- `debug`: logs debug records and startup runtime/build metadata. +- `info`: logs info records and above. This is the default. +- `warning` or `warn`: logs warning records and above. +- `error`: logs error records only. +- `quiet` or `none`: disables logs. + +When built with the `debug` build tag and `GNARK_LOG_LEVEL` is unset, the default level is `debug`. + ## Supported Proving Systems and Curves `gnark` currently supports: From 346243cfdd295f780759930d497fa0cee6a29724 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Sun, 17 May 2026 22:19:01 +0000 Subject: [PATCH 04/44] feat: add zerolog adapter for compatibility --- internal/logger/zerolog.go | 188 +++++++++++++++++++++++++++++++++++++ logger/logger.go | 79 +--------------- 2 files changed, 189 insertions(+), 78 deletions(-) create mode 100644 internal/logger/zerolog.go diff --git a/internal/logger/zerolog.go b/internal/logger/zerolog.go new file mode 100644 index 0000000000..7d6aa4dc59 --- /dev/null +++ b/internal/logger/zerolog.go @@ -0,0 +1,188 @@ +package logger + +import ( + "bytes" + "context" + "encoding/json" + "log/slog" + "sort" + + "github.com/rs/zerolog" +) + +// SlogAdapter is the set of logger types that can be adapted to slog. +type SlogAdapter interface { + *slog.Logger | zerolog.Logger +} + +// AsSlog returns l as a slog logger. It accepts *slog.Logger and, for legacy +// compatibility, zerolog.Logger. +// +// The zerolog support is deprecated and may be removed in future versions. +// Users should prefer using slog.Logger directly, as it is the standard library +// logger in Go 1.21 and later, and it is the default logger used by gnark. +func AsSlog[T SlogAdapter](l T) (*slog.Logger, bool) { + switch l := any(l).(type) { + case *slog.Logger: + if l == nil { + return nil, false + } + return l, true + case zerolog.Logger: + return FromZerolog(l), true + default: + return nil, false + } +} + +// FromZerolog adapts a legacy zerolog logger to slog. +func FromZerolog(log zerolog.Logger) *slog.Logger { + return slog.New(zerologHandler{logger: log}) +} + +// ToZerolog adapts a slog logger to the legacy zerolog API. +func ToZerolog(log *slog.Logger) zerolog.Logger { + return zerolog.New(slogLevelWriter{logger: log}).Level(zerolog.TraceLevel) +} + +type zerologHandler struct { + logger zerolog.Logger + attrs []slog.Attr +} + +func (h zerologHandler) Enabled(_ context.Context, level slog.Level) bool { + return h.logger.GetLevel() <= zerologLevel(level) && h.logger.GetLevel() != zerolog.Disabled +} + +func (h zerologHandler) Handle(_ context.Context, record slog.Record) error { + event := h.logger.WithLevel(zerologLevel(record.Level)) + for _, attr := range h.attrs { + event = addAttr(event, attr) + } + record.Attrs(func(attr slog.Attr) bool { + event = addAttr(event, attr) + return true + }) + event.Msg(record.Message) + return nil +} + +func (h zerologHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + h.attrs = append(append([]slog.Attr{}, h.attrs...), attrs...) + return h +} + +func (h zerologHandler) WithGroup(string) slog.Handler { + return h +} + +func addAttr(event *zerolog.Event, attr slog.Attr) *zerolog.Event { + attr.Value = attr.Value.Resolve() + switch attr.Value.Kind() { + case slog.KindString: + return event.Str(attr.Key, attr.Value.String()) + case slog.KindInt64: + return event.Int64(attr.Key, attr.Value.Int64()) + case slog.KindUint64: + return event.Uint64(attr.Key, attr.Value.Uint64()) + case slog.KindFloat64: + return event.Float64(attr.Key, attr.Value.Float64()) + case slog.KindBool: + return event.Bool(attr.Key, attr.Value.Bool()) + case slog.KindDuration: + return event.Dur(attr.Key, attr.Value.Duration()) + case slog.KindTime: + return event.Time(attr.Key, attr.Value.Time()) + default: + return event.Interface(attr.Key, attr.Value.Any()) + } +} + +func zerologLevel(level slog.Level) zerolog.Level { + switch { + case level <= LevelTrace: + return zerolog.TraceLevel + case level <= slog.LevelDebug: + return zerolog.DebugLevel + case level < slog.LevelWarn: + return zerolog.InfoLevel + case level < slog.LevelError: + return zerolog.WarnLevel + default: + return zerolog.ErrorLevel + } +} + +type slogLevelWriter struct { + logger *slog.Logger +} + +func (w slogLevelWriter) Write(p []byte) (int, error) { + return w.WriteLevel(zerolog.NoLevel, p) +} + +func (w slogLevelWriter) WriteLevel(level zerolog.Level, p []byte) (int, error) { + level, msg, attrs := decodeZerologEvent(level, p) + w.logger.LogAttrs(context.Background(), slogLevel(level), msg, attrs...) + return len(p), nil +} + +func decodeZerologEvent(level zerolog.Level, p []byte) (zerolog.Level, string, []slog.Attr) { + decoder := json.NewDecoder(bytes.NewReader(p)) + decoder.UseNumber() + + var fields map[string]any + if err := decoder.Decode(&fields); err != nil { + return level, string(bytes.TrimSpace(p)), nil + } + + if level == zerolog.NoLevel { + level = parseZerologLevel(fields[zerolog.LevelFieldName]) + } + + msg, _ := fields[zerolog.MessageFieldName].(string) + delete(fields, zerolog.LevelFieldName) + delete(fields, zerolog.MessageFieldName) + delete(fields, zerolog.TimestampFieldName) + + keys := make([]string, 0, len(fields)) + for key := range fields { + keys = append(keys, key) + } + sort.Strings(keys) + + attrs := make([]slog.Attr, 0, len(keys)) + for _, key := range keys { + attrs = append(attrs, slog.Any(key, fields[key])) + } + return level, msg, attrs +} + +func parseZerologLevel(value any) zerolog.Level { + level, ok := value.(string) + if !ok { + return zerolog.InfoLevel + } + parsed, err := zerolog.ParseLevel(level) + if err != nil { + return zerolog.InfoLevel + } + return parsed +} + +func slogLevel(level zerolog.Level) slog.Level { + switch level { + case zerolog.TraceLevel: + return LevelTrace + case zerolog.DebugLevel: + return slog.LevelDebug + case zerolog.InfoLevel, zerolog.NoLevel: + return slog.LevelInfo + case zerolog.WarnLevel: + return slog.LevelWarn + case zerolog.ErrorLevel, zerolog.FatalLevel, zerolog.PanicLevel: + return slog.LevelError + default: + return slog.LevelInfo + } +} diff --git a/logger/logger.go b/logger/logger.go index 40e6100f60..20c153e241 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -5,12 +5,7 @@ package logger import ( - "bytes" - "context" - "encoding/json" "io" - "log/slog" - "sort" "sync" "testing" @@ -68,7 +63,7 @@ func Logger() zerolog.Logger { } func newSlogBackedZerolog() zerolog.Logger { - return zerolog.New(slogLevelWriter{}).Level(zerolog.TraceLevel) + return internallogger.ToZerolog(internallogger.Logger()) } func warnDeprecated() { @@ -79,75 +74,3 @@ func warnDeprecated() { internallogger.Logger().Warn(deprecationMessage) }) } - -type slogLevelWriter struct{} - -func (slogLevelWriter) Write(p []byte) (int, error) { - return slogLevelWriter{}.WriteLevel(zerolog.NoLevel, p) -} - -func (slogLevelWriter) WriteLevel(level zerolog.Level, p []byte) (int, error) { - level, msg, attrs := decodeZerologEvent(level, p) - internallogger.Logger().LogAttrs(context.Background(), slogLevel(level), msg, attrs...) - return len(p), nil -} - -func decodeZerologEvent(level zerolog.Level, p []byte) (zerolog.Level, string, []slog.Attr) { - decoder := json.NewDecoder(bytes.NewReader(p)) - decoder.UseNumber() - - var fields map[string]any - if err := decoder.Decode(&fields); err != nil { - return level, string(bytes.TrimSpace(p)), nil - } - - if level == zerolog.NoLevel { - level = zerologLevel(fields[zerolog.LevelFieldName]) - } - - msg, _ := fields[zerolog.MessageFieldName].(string) - delete(fields, zerolog.LevelFieldName) - delete(fields, zerolog.MessageFieldName) - delete(fields, zerolog.TimestampFieldName) - - keys := make([]string, 0, len(fields)) - for key := range fields { - keys = append(keys, key) - } - sort.Strings(keys) - - attrs := make([]slog.Attr, 0, len(keys)) - for _, key := range keys { - attrs = append(attrs, slog.Any(key, fields[key])) - } - return level, msg, attrs -} - -func zerologLevel(value any) zerolog.Level { - level, ok := value.(string) - if !ok { - return zerolog.InfoLevel - } - parsed, err := zerolog.ParseLevel(level) - if err != nil { - return zerolog.InfoLevel - } - return parsed -} - -func slogLevel(level zerolog.Level) slog.Level { - switch level { - case zerolog.TraceLevel: - return internallogger.LevelTrace - case zerolog.DebugLevel: - return slog.LevelDebug - case zerolog.InfoLevel, zerolog.NoLevel: - return slog.LevelInfo - case zerolog.WarnLevel: - return slog.LevelWarn - case zerolog.ErrorLevel, zerolog.FatalLevel, zerolog.PanicLevel: - return slog.LevelError - default: - return slog.LevelInfo - } -} From efcf114ee8e7a4b77e21527885182c6e0e976cf6 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Sun, 17 May 2026 22:19:14 +0000 Subject: [PATCH 05/44] feat: add trace log level --- internal/logger/logger.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 98b9869509..029eb45c2b 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -45,6 +45,10 @@ func Logger() *slog.Logger { return defaultLogger } +func Trace(log *slog.Logger, msg string, attrs ...slog.Attr) { + log.LogAttrs(context.Background(), LevelTrace, msg, attrs...) +} + func newHandler(w io.Writer, level slog.Level) slog.Handler { return slog.NewTextHandler(w, &slog.HandlerOptions{ // We want to include the source for trace logs, but not for higher From 851b92309405e2c78e4364778c5cd37e76c318b8 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Sun, 17 May 2026 22:32:40 +0000 Subject: [PATCH 06/44] feat: use slog in icicle prover --- .../icicle/groth16/bls12-377/icicle.go | 143 +++++++++--------- .../icicle/groth16/bls12-381/icicle.go | 143 +++++++++--------- .../icicle/groth16/bn254/icicle.go | 143 +++++++++--------- .../icicle/groth16/bw6-761/icicle.go | 143 +++++++++--------- .../templates/groth16.icicle.go.tmpl | 142 ++++++++--------- 5 files changed, 364 insertions(+), 350 deletions(-) diff --git a/backend/accelerated/icicle/groth16/bls12-377/icicle.go b/backend/accelerated/icicle/groth16/bls12-377/icicle.go index 39c8ecd1b9..bbecc58bf7 100644 --- a/backend/accelerated/icicle/groth16/bls12-377/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-377/icicle.go @@ -20,6 +20,8 @@ import ( "time" "unsafe" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" curve "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" @@ -34,7 +36,8 @@ import ( cs "github.com/consensys/gnark/constraint/bls12-377" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/internal/logger" icicle_core "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/core" icicle_bls12377 "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/curves/bls12377" @@ -184,7 +187,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { /************************* Pin vectors to GPU if requested ***************************/ if pk.PinToGPU { log := logger.Logger() - log.Info().Msg("PinToGPU enabled - pre-loading all vectors to GPU memory") + log.Debug("PinToGPU enabled - pre-loading all vectors to GPU memory") pinVectorsDone := make(chan struct{}) icicle_runtime.RunOnDevice(device, func(args ...any) { @@ -193,7 +196,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { var err error // Pin G1.A - log.Debug().Msg("Pinning G1.A to GPU") + logger.Trace(log, "Pinning G1.A to GPU") g1AHost := icicle_core.HostSliceFromElements(pk.G1.A) pk.PinnedG1Device.A, err = loadG1(g1AHost) if err != nil { @@ -201,7 +204,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.B - log.Debug().Msg("Pinning G1.B to GPU") + logger.Trace(log, "Pinning G1.B to GPU") g1BHost := icicle_core.HostSliceFromElements(pk.G1.B) pk.PinnedG1Device.B, err = loadG1(g1BHost) if err != nil { @@ -209,7 +212,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.K - log.Debug().Msg("Pinning G1.K to GPU") + logger.Trace(log, "Pinning G1.K to GPU") g1KHost := icicle_core.HostSliceFromElements(pk.G1.K) pk.PinnedG1Device.K, err = loadG1(g1KHost) if err != nil { @@ -217,7 +220,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.Z - log.Debug().Msg("Pinning G1.Z to GPU") + logger.Trace(log, "Pinning G1.Z to GPU") g1ZHost := icicle_core.HostSliceFromElements(pk.G1.Z) pk.PinnedG1Device.Z, err = loadG1(g1ZHost) if err != nil { @@ -225,7 +228,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G2.B - log.Debug().Msg("Pinning G2.B to GPU") + logger.Trace(log, "Pinning G2.B to GPU") g2BHost := icicle_core.HostSliceFromElements(pk.G2.B) pk.PinnedG2Device.B, err = loadG2(g2BHost) if err != nil { @@ -237,7 +240,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { pk.CommitmentKeysDevice.BasisExpSigma = make([]icicle_core.DeviceSlice, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { if len(pk.CommitmentKeys[i].Basis) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key basis to GPU") + logger.Trace(log, "Pinning commitment key basis to GPU", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) pk.CommitmentKeysDevice.Basis[i], err = loadG1Raw(ckBasisHost) if err != nil { @@ -245,7 +248,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } if len(pk.CommitmentKeys[i].BasisExpSigma) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key BasisExpSigma to GPU") + logger.Trace(log, "Pinning commitment key BasisExpSigma to GPU", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) pk.CommitmentKeysDevice.BasisExpSigma[i], err = loadG1Raw(ckBasisExpSigmaHost) if err != nil { @@ -255,7 +258,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } - log.Info().Msg("All vectors pinned to GPU successfully") + log.Debug("All vectors pinned to GPU successfully") }) <-pinVectorsDone } @@ -325,7 +328,7 @@ func loadG1(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G1 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -338,7 +341,7 @@ func loadG1Raw(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Dev // NO conversion - keep Montgomery form for commitment keys if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (raw, Montgomery preserved)") + logger.Trace(log, "Loaded G1 vector (raw, Montgomery preserved)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -353,7 +356,7 @@ func loadG2(hostSlice icicle_core.HostSlice[curve.G2Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G2 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G2 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -790,7 +793,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "icicle").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) @@ -798,7 +801,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic needsSetup := pk.deviceInfo == nil pk.setupMu.Unlock() if needsSetup { - log.Debug().Msg("precomputing proving key in GPU") + logger.Trace(log, "precomputing proving key in GPU") } if err := pk.setupDevicePointers(&device); err != nil { return nil, fmt.Errorf("setup device pointers: %w", err) @@ -839,10 +842,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.Basis) && pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key basis for MSM") + logger.Trace(log, "Using pinned commitment key basis for MSM", slog.Int("commitment", i)) ckBasisDevice = pk.CommitmentKeysDevice.Basis[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key basis for MSM") + logger.Trace(log, "Loading commitment key basis for MSM", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) var err error ckBasisDevice, err = loadG1Raw(ckBasisHost) @@ -854,7 +857,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && ckBasisDevice.AsUnsafePointer() != nil { ckBasisDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key basis") + logger.Trace(log, "Freed commitment key basis", slog.Int("commitment", i)) } }() @@ -917,10 +920,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisExpSigmaDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.BasisExpSigma) && pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Using pinned commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaDevice = pk.CommitmentKeysDevice.BasisExpSigma[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Loading commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) var err error ckBasisExpSigmaDevice, err = loadG1Raw(ckBasisExpSigmaHost) @@ -938,7 +941,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic if shouldFree && ckBasisExpSigmaDevice.AsUnsafePointer() != nil { ckBasisExpSigmaDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key BasisExpSigma") + logger.Trace(log, "Freed commitment key BasisExpSigma", slog.Int("commitment", i)) } } close(ckBasisExpSigmaMsmBatchDone) @@ -955,11 +958,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic privateCommittedValuesDevice[i].Free() } } - log.Debug().Msg("Freed all privateCommittedValuesDevice after POK") + logger.Trace(log, "Freed all privateCommittedValuesDevice after POK") }) if isProfileMode { - log.Debug().Dur("took", time.Since(startPoKBatch)).Msg("ICICLE Batch Proof of Knowledge") + logger.Trace(log, "ICICLE Batch Proof of Knowledge", slog.Duration("took", time.Since(startPoKBatch))) } } // compute challenge for folding the PoKs from the commitments @@ -1056,11 +1059,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.B from GPU") + logger.Trace(log, "Using pinned G1.B from GPU") g1BDevice = pk.PinnedG1Device.B shouldFree = false } else { - log.Debug().Msg("Loading G1.B for BS1 MSM") + logger.Trace(log, "Loading G1.B for BS1 MSM") g1BHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.B) var err error g1BDevice, err = loadG1(g1BHost) @@ -1072,7 +1075,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1BDevice.AsUnsafePointer() != nil { g1BDevice.Free() - log.Debug().Msg("Freed G1.B after BS1 MSM") + logger.Trace(log, "Freed G1.B after BS1 MSM") } }() @@ -1086,11 +1089,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic bs1 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs1") } bs1.AddMixed(&pk.G1.Beta) @@ -1104,11 +1107,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.A.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.A from GPU") + logger.Trace(log, "Using pinned G1.A from GPU") g1ADevice = pk.PinnedG1Device.A shouldFree = false } else { - log.Debug().Msg("Loading G1.A for AR1 MSM") + logger.Trace(log, "Loading G1.A for AR1 MSM") g1AHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.A) var err error g1ADevice, err = loadG1(g1AHost) @@ -1120,7 +1123,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1ADevice.AsUnsafePointer() != nil { g1ADevice.Free() - log.Debug().Msg("Freed G1.A after AR1 MSM") + logger.Trace(log, "Freed G1.A after AR1 MSM") } }() @@ -1134,11 +1137,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic ar = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Ar1") } ar.AddMixed(&pk.G1.Alpha) @@ -1153,11 +1156,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFreeZ bool if pk.PinToGPU && pk.PinnedG1Device.Z.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.Z from GPU") + logger.Trace(log, "Using pinned G1.Z from GPU") g1ZDevice = pk.PinnedG1Device.Z shouldFreeZ = false } else { - log.Debug().Msg("Loading G1.Z for KRS MSM") + logger.Trace(log, "Loading G1.Z for KRS MSM") g1ZHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.Z) var err error g1ZDevice, err = loadG1(g1ZHost) @@ -1169,7 +1172,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeZ && g1ZDevice.AsUnsafePointer() != nil { g1ZDevice.Free() - log.Debug().Msg("Freed G1.Z after KRS MSM") + logger.Trace(log, "Freed G1.Z after KRS MSM") } }() @@ -1186,22 +1189,22 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs2 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs2") } var g1KDevice icicle_core.DeviceSlice var shouldFreeK bool if pk.PinToGPU && pk.PinnedG1Device.K.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.K from GPU") + logger.Trace(log, "Using pinned G1.K from GPU") g1KDevice = pk.PinnedG1Device.K shouldFreeK = false } else { - log.Debug().Msg("Loading G1.K for KRS MSM") + logger.Trace(log, "Loading G1.K for KRS MSM") g1KHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.K) var err error g1KDevice, err = loadG1(g1KHost) @@ -1213,7 +1216,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeK && g1KDevice.AsUnsafePointer() != nil { g1KDevice.Free() - log.Debug().Msg("Freed G1.K after KRS MSM") + logger.Trace(log, "Freed G1.K after KRS MSM") } }() @@ -1239,11 +1242,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs") } krs.AddMixed(&deltas[2]) @@ -1266,11 +1269,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG2Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G2.B from GPU") + logger.Trace(log, "Using pinned G2.B from GPU") g2BDevice = pk.PinnedG2Device.B shouldFree = false } else { - log.Debug().Msg("Loading G2.B for BS2 MSM") + logger.Trace(log, "Loading G2.B for BS2 MSM") g2BHost := (icicle_core.HostSlice[curve.G2Affine])(pk.G2.B) var err error g2BDevice, err = loadG2(g2BHost) @@ -1282,7 +1285,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g2BDevice.AsUnsafePointer() != nil { g2BDevice.Free() - log.Debug().Msg("Freed G2.B after BS2 MSM") + logger.Trace(log, "Freed G2.B after BS2 MSM") } }() @@ -1299,11 +1302,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic Bs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs2 G2") } deltaS.FromAffine(&pk.G2.Delta) @@ -1341,18 +1344,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic }) <-computeKrsDone - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesADevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesBDevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free h failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) } }) @@ -1428,7 +1431,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic icicle_ntt.Ntt(scalarsDevice, icicle_core.KForward, &cfg, scalarsDevice) icicle_runtime.SynchronizeStream(scalarsStream) if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: NTT + INTT") + logger.Trace(log, "computeH: NTT + INTT", slog.Duration("took", time.Since(start))) } channel <- scalarsDevice runtime.KeepAlive(scalars) // keep host buffer alive until the async copy/NTT completes @@ -1462,7 +1465,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("mul a den in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: vecOps") + logger.Trace(log, "computeH: vecOps", slog.Duration("took", time.Since(start))) } defer bDevice.Free() defer cDevice.Free() @@ -1475,14 +1478,14 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("ntt a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: INTT final") + logger.Trace(log, "computeH: INTT final", slog.Duration("took", time.Since(start))) } if err := icicle_bls12377.FromMontgomery(aDevice); err != icicle_runtime.Success { panic(fmt.Sprintf("fromMontgomery a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(startTotal)).Msg("computeH: Total") + logger.Trace(log, "computeH: Total", slog.Duration("took", time.Since(startTotal))) } return aDevice } @@ -1503,47 +1506,47 @@ func (pk *ProvingKey) FreeGPUResources() { // Free pinned G1 vectors if pk.PinnedG1Device.A.AsUnsafePointer() != nil { pk.PinnedG1Device.A.Free() - log.Debug().Msg("Freed pinned G1.A") + logger.Trace(log, "Freed pinned G1.A") } if pk.PinnedG1Device.B.AsUnsafePointer() != nil { pk.PinnedG1Device.B.Free() - log.Debug().Msg("Freed pinned G1.B") + logger.Trace(log, "Freed pinned G1.B") } if pk.PinnedG1Device.K.AsUnsafePointer() != nil { pk.PinnedG1Device.K.Free() - log.Debug().Msg("Freed pinned G1.K") + logger.Trace(log, "Freed pinned G1.K") } if pk.PinnedG1Device.Z.AsUnsafePointer() != nil { pk.PinnedG1Device.Z.Free() - log.Debug().Msg("Freed pinned G1.Z") + logger.Trace(log, "Freed pinned G1.Z") } // Free pinned G2 vectors if pk.PinnedG2Device.B.AsUnsafePointer() != nil { pk.PinnedG2Device.B.Free() - log.Debug().Msg("Freed pinned G2.B") + logger.Trace(log, "Freed pinned G2.B") } // Free DenDevice if pk.DenDevice.AsUnsafePointer() != nil { pk.DenDevice.Free() - log.Debug().Msg("Freed DenDevice") + logger.Trace(log, "Freed DenDevice") } // Free pinned commitment keys for i := range pk.CommitmentKeysDevice.Basis { if pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.Basis[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key basis") + logger.Trace(log, "Freed pinned commitment key basis", slog.Int("commitment", i)) } } for i := range pk.CommitmentKeysDevice.BasisExpSigma { if pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.BasisExpSigma[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key BasisExpSigma") + logger.Trace(log, "Freed pinned commitment key BasisExpSigma", slog.Int("commitment", i)) } } - log.Info().Msg("All GPU resources freed") + log.Debug("All GPU resources freed") pk.deviceInfo = nil } diff --git a/backend/accelerated/icicle/groth16/bls12-381/icicle.go b/backend/accelerated/icicle/groth16/bls12-381/icicle.go index 5dda9ebf14..0f52d0b66c 100644 --- a/backend/accelerated/icicle/groth16/bls12-381/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-381/icicle.go @@ -20,6 +20,8 @@ import ( "time" "unsafe" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" curve "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" @@ -34,7 +36,8 @@ import ( cs "github.com/consensys/gnark/constraint/bls12-381" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/internal/logger" icicle_core "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/core" icicle_bls12381 "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/curves/bls12381" @@ -184,7 +187,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { /************************* Pin vectors to GPU if requested ***************************/ if pk.PinToGPU { log := logger.Logger() - log.Info().Msg("PinToGPU enabled - pre-loading all vectors to GPU memory") + log.Debug("PinToGPU enabled - pre-loading all vectors to GPU memory") pinVectorsDone := make(chan struct{}) icicle_runtime.RunOnDevice(device, func(args ...any) { @@ -193,7 +196,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { var err error // Pin G1.A - log.Debug().Msg("Pinning G1.A to GPU") + logger.Trace(log, "Pinning G1.A to GPU") g1AHost := icicle_core.HostSliceFromElements(pk.G1.A) pk.PinnedG1Device.A, err = loadG1(g1AHost) if err != nil { @@ -201,7 +204,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.B - log.Debug().Msg("Pinning G1.B to GPU") + logger.Trace(log, "Pinning G1.B to GPU") g1BHost := icicle_core.HostSliceFromElements(pk.G1.B) pk.PinnedG1Device.B, err = loadG1(g1BHost) if err != nil { @@ -209,7 +212,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.K - log.Debug().Msg("Pinning G1.K to GPU") + logger.Trace(log, "Pinning G1.K to GPU") g1KHost := icicle_core.HostSliceFromElements(pk.G1.K) pk.PinnedG1Device.K, err = loadG1(g1KHost) if err != nil { @@ -217,7 +220,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.Z - log.Debug().Msg("Pinning G1.Z to GPU") + logger.Trace(log, "Pinning G1.Z to GPU") g1ZHost := icicle_core.HostSliceFromElements(pk.G1.Z) pk.PinnedG1Device.Z, err = loadG1(g1ZHost) if err != nil { @@ -225,7 +228,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G2.B - log.Debug().Msg("Pinning G2.B to GPU") + logger.Trace(log, "Pinning G2.B to GPU") g2BHost := icicle_core.HostSliceFromElements(pk.G2.B) pk.PinnedG2Device.B, err = loadG2(g2BHost) if err != nil { @@ -237,7 +240,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { pk.CommitmentKeysDevice.BasisExpSigma = make([]icicle_core.DeviceSlice, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { if len(pk.CommitmentKeys[i].Basis) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key basis to GPU") + logger.Trace(log, "Pinning commitment key basis to GPU", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) pk.CommitmentKeysDevice.Basis[i], err = loadG1Raw(ckBasisHost) if err != nil { @@ -245,7 +248,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } if len(pk.CommitmentKeys[i].BasisExpSigma) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key BasisExpSigma to GPU") + logger.Trace(log, "Pinning commitment key BasisExpSigma to GPU", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) pk.CommitmentKeysDevice.BasisExpSigma[i], err = loadG1Raw(ckBasisExpSigmaHost) if err != nil { @@ -255,7 +258,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } - log.Info().Msg("All vectors pinned to GPU successfully") + log.Debug("All vectors pinned to GPU successfully") }) <-pinVectorsDone } @@ -325,7 +328,7 @@ func loadG1(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G1 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -338,7 +341,7 @@ func loadG1Raw(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Dev // NO conversion - keep Montgomery form for commitment keys if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (raw, Montgomery preserved)") + logger.Trace(log, "Loaded G1 vector (raw, Montgomery preserved)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -353,7 +356,7 @@ func loadG2(hostSlice icicle_core.HostSlice[curve.G2Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G2 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G2 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -790,7 +793,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "icicle").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) @@ -798,7 +801,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic needsSetup := pk.deviceInfo == nil pk.setupMu.Unlock() if needsSetup { - log.Debug().Msg("precomputing proving key in GPU") + logger.Trace(log, "precomputing proving key in GPU") } if err := pk.setupDevicePointers(&device); err != nil { return nil, fmt.Errorf("setup device pointers: %w", err) @@ -839,10 +842,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.Basis) && pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key basis for MSM") + logger.Trace(log, "Using pinned commitment key basis for MSM", slog.Int("commitment", i)) ckBasisDevice = pk.CommitmentKeysDevice.Basis[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key basis for MSM") + logger.Trace(log, "Loading commitment key basis for MSM", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) var err error ckBasisDevice, err = loadG1Raw(ckBasisHost) @@ -854,7 +857,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && ckBasisDevice.AsUnsafePointer() != nil { ckBasisDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key basis") + logger.Trace(log, "Freed commitment key basis", slog.Int("commitment", i)) } }() @@ -917,10 +920,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisExpSigmaDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.BasisExpSigma) && pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Using pinned commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaDevice = pk.CommitmentKeysDevice.BasisExpSigma[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Loading commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) var err error ckBasisExpSigmaDevice, err = loadG1Raw(ckBasisExpSigmaHost) @@ -938,7 +941,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic if shouldFree && ckBasisExpSigmaDevice.AsUnsafePointer() != nil { ckBasisExpSigmaDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key BasisExpSigma") + logger.Trace(log, "Freed commitment key BasisExpSigma", slog.Int("commitment", i)) } } close(ckBasisExpSigmaMsmBatchDone) @@ -955,11 +958,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic privateCommittedValuesDevice[i].Free() } } - log.Debug().Msg("Freed all privateCommittedValuesDevice after POK") + logger.Trace(log, "Freed all privateCommittedValuesDevice after POK") }) if isProfileMode { - log.Debug().Dur("took", time.Since(startPoKBatch)).Msg("ICICLE Batch Proof of Knowledge") + logger.Trace(log, "ICICLE Batch Proof of Knowledge", slog.Duration("took", time.Since(startPoKBatch))) } } // compute challenge for folding the PoKs from the commitments @@ -1056,11 +1059,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.B from GPU") + logger.Trace(log, "Using pinned G1.B from GPU") g1BDevice = pk.PinnedG1Device.B shouldFree = false } else { - log.Debug().Msg("Loading G1.B for BS1 MSM") + logger.Trace(log, "Loading G1.B for BS1 MSM") g1BHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.B) var err error g1BDevice, err = loadG1(g1BHost) @@ -1072,7 +1075,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1BDevice.AsUnsafePointer() != nil { g1BDevice.Free() - log.Debug().Msg("Freed G1.B after BS1 MSM") + logger.Trace(log, "Freed G1.B after BS1 MSM") } }() @@ -1086,11 +1089,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic bs1 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs1") } bs1.AddMixed(&pk.G1.Beta) @@ -1104,11 +1107,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.A.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.A from GPU") + logger.Trace(log, "Using pinned G1.A from GPU") g1ADevice = pk.PinnedG1Device.A shouldFree = false } else { - log.Debug().Msg("Loading G1.A for AR1 MSM") + logger.Trace(log, "Loading G1.A for AR1 MSM") g1AHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.A) var err error g1ADevice, err = loadG1(g1AHost) @@ -1120,7 +1123,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1ADevice.AsUnsafePointer() != nil { g1ADevice.Free() - log.Debug().Msg("Freed G1.A after AR1 MSM") + logger.Trace(log, "Freed G1.A after AR1 MSM") } }() @@ -1134,11 +1137,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic ar = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Ar1") } ar.AddMixed(&pk.G1.Alpha) @@ -1153,11 +1156,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFreeZ bool if pk.PinToGPU && pk.PinnedG1Device.Z.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.Z from GPU") + logger.Trace(log, "Using pinned G1.Z from GPU") g1ZDevice = pk.PinnedG1Device.Z shouldFreeZ = false } else { - log.Debug().Msg("Loading G1.Z for KRS MSM") + logger.Trace(log, "Loading G1.Z for KRS MSM") g1ZHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.Z) var err error g1ZDevice, err = loadG1(g1ZHost) @@ -1169,7 +1172,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeZ && g1ZDevice.AsUnsafePointer() != nil { g1ZDevice.Free() - log.Debug().Msg("Freed G1.Z after KRS MSM") + logger.Trace(log, "Freed G1.Z after KRS MSM") } }() @@ -1186,22 +1189,22 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs2 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs2") } var g1KDevice icicle_core.DeviceSlice var shouldFreeK bool if pk.PinToGPU && pk.PinnedG1Device.K.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.K from GPU") + logger.Trace(log, "Using pinned G1.K from GPU") g1KDevice = pk.PinnedG1Device.K shouldFreeK = false } else { - log.Debug().Msg("Loading G1.K for KRS MSM") + logger.Trace(log, "Loading G1.K for KRS MSM") g1KHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.K) var err error g1KDevice, err = loadG1(g1KHost) @@ -1213,7 +1216,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeK && g1KDevice.AsUnsafePointer() != nil { g1KDevice.Free() - log.Debug().Msg("Freed G1.K after KRS MSM") + logger.Trace(log, "Freed G1.K after KRS MSM") } }() @@ -1239,11 +1242,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs") } krs.AddMixed(&deltas[2]) @@ -1266,11 +1269,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG2Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G2.B from GPU") + logger.Trace(log, "Using pinned G2.B from GPU") g2BDevice = pk.PinnedG2Device.B shouldFree = false } else { - log.Debug().Msg("Loading G2.B for BS2 MSM") + logger.Trace(log, "Loading G2.B for BS2 MSM") g2BHost := (icicle_core.HostSlice[curve.G2Affine])(pk.G2.B) var err error g2BDevice, err = loadG2(g2BHost) @@ -1282,7 +1285,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g2BDevice.AsUnsafePointer() != nil { g2BDevice.Free() - log.Debug().Msg("Freed G2.B after BS2 MSM") + logger.Trace(log, "Freed G2.B after BS2 MSM") } }() @@ -1299,11 +1302,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic Bs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs2 G2") } deltaS.FromAffine(&pk.G2.Delta) @@ -1341,18 +1344,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic }) <-computeKrsDone - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesADevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesBDevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free h failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) } }) @@ -1428,7 +1431,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic icicle_ntt.Ntt(scalarsDevice, icicle_core.KForward, &cfg, scalarsDevice) icicle_runtime.SynchronizeStream(scalarsStream) if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: NTT + INTT") + logger.Trace(log, "computeH: NTT + INTT", slog.Duration("took", time.Since(start))) } channel <- scalarsDevice runtime.KeepAlive(scalars) // keep host buffer alive until the async copy/NTT completes @@ -1462,7 +1465,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("mul a den in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: vecOps") + logger.Trace(log, "computeH: vecOps", slog.Duration("took", time.Since(start))) } defer bDevice.Free() defer cDevice.Free() @@ -1475,14 +1478,14 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("ntt a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: INTT final") + logger.Trace(log, "computeH: INTT final", slog.Duration("took", time.Since(start))) } if err := icicle_bls12381.FromMontgomery(aDevice); err != icicle_runtime.Success { panic(fmt.Sprintf("fromMontgomery a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(startTotal)).Msg("computeH: Total") + logger.Trace(log, "computeH: Total", slog.Duration("took", time.Since(startTotal))) } return aDevice } @@ -1503,47 +1506,47 @@ func (pk *ProvingKey) FreeGPUResources() { // Free pinned G1 vectors if pk.PinnedG1Device.A.AsUnsafePointer() != nil { pk.PinnedG1Device.A.Free() - log.Debug().Msg("Freed pinned G1.A") + logger.Trace(log, "Freed pinned G1.A") } if pk.PinnedG1Device.B.AsUnsafePointer() != nil { pk.PinnedG1Device.B.Free() - log.Debug().Msg("Freed pinned G1.B") + logger.Trace(log, "Freed pinned G1.B") } if pk.PinnedG1Device.K.AsUnsafePointer() != nil { pk.PinnedG1Device.K.Free() - log.Debug().Msg("Freed pinned G1.K") + logger.Trace(log, "Freed pinned G1.K") } if pk.PinnedG1Device.Z.AsUnsafePointer() != nil { pk.PinnedG1Device.Z.Free() - log.Debug().Msg("Freed pinned G1.Z") + logger.Trace(log, "Freed pinned G1.Z") } // Free pinned G2 vectors if pk.PinnedG2Device.B.AsUnsafePointer() != nil { pk.PinnedG2Device.B.Free() - log.Debug().Msg("Freed pinned G2.B") + logger.Trace(log, "Freed pinned G2.B") } // Free DenDevice if pk.DenDevice.AsUnsafePointer() != nil { pk.DenDevice.Free() - log.Debug().Msg("Freed DenDevice") + logger.Trace(log, "Freed DenDevice") } // Free pinned commitment keys for i := range pk.CommitmentKeysDevice.Basis { if pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.Basis[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key basis") + logger.Trace(log, "Freed pinned commitment key basis", slog.Int("commitment", i)) } } for i := range pk.CommitmentKeysDevice.BasisExpSigma { if pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.BasisExpSigma[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key BasisExpSigma") + logger.Trace(log, "Freed pinned commitment key BasisExpSigma", slog.Int("commitment", i)) } } - log.Info().Msg("All GPU resources freed") + log.Debug("All GPU resources freed") pk.deviceInfo = nil } diff --git a/backend/accelerated/icicle/groth16/bn254/icicle.go b/backend/accelerated/icicle/groth16/bn254/icicle.go index f0c33bc76c..2680cd8b00 100644 --- a/backend/accelerated/icicle/groth16/bn254/icicle.go +++ b/backend/accelerated/icicle/groth16/bn254/icicle.go @@ -20,6 +20,8 @@ import ( "time" "unsafe" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" curve "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" @@ -34,7 +36,8 @@ import ( cs "github.com/consensys/gnark/constraint/bn254" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/internal/logger" icicle_core "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/core" icicle_bn254 "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/curves/bn254" @@ -184,7 +187,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { /************************* Pin vectors to GPU if requested ***************************/ if pk.PinToGPU { log := logger.Logger() - log.Info().Msg("PinToGPU enabled - pre-loading all vectors to GPU memory") + log.Debug("PinToGPU enabled - pre-loading all vectors to GPU memory") pinVectorsDone := make(chan struct{}) icicle_runtime.RunOnDevice(device, func(args ...any) { @@ -193,7 +196,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { var err error // Pin G1.A - log.Debug().Msg("Pinning G1.A to GPU") + logger.Trace(log, "Pinning G1.A to GPU") g1AHost := icicle_core.HostSliceFromElements(pk.G1.A) pk.PinnedG1Device.A, err = loadG1(g1AHost) if err != nil { @@ -201,7 +204,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.B - log.Debug().Msg("Pinning G1.B to GPU") + logger.Trace(log, "Pinning G1.B to GPU") g1BHost := icicle_core.HostSliceFromElements(pk.G1.B) pk.PinnedG1Device.B, err = loadG1(g1BHost) if err != nil { @@ -209,7 +212,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.K - log.Debug().Msg("Pinning G1.K to GPU") + logger.Trace(log, "Pinning G1.K to GPU") g1KHost := icicle_core.HostSliceFromElements(pk.G1.K) pk.PinnedG1Device.K, err = loadG1(g1KHost) if err != nil { @@ -217,7 +220,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.Z - log.Debug().Msg("Pinning G1.Z to GPU") + logger.Trace(log, "Pinning G1.Z to GPU") g1ZHost := icicle_core.HostSliceFromElements(pk.G1.Z) pk.PinnedG1Device.Z, err = loadG1(g1ZHost) if err != nil { @@ -225,7 +228,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G2.B - log.Debug().Msg("Pinning G2.B to GPU") + logger.Trace(log, "Pinning G2.B to GPU") g2BHost := icicle_core.HostSliceFromElements(pk.G2.B) pk.PinnedG2Device.B, err = loadG2(g2BHost) if err != nil { @@ -237,7 +240,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { pk.CommitmentKeysDevice.BasisExpSigma = make([]icicle_core.DeviceSlice, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { if len(pk.CommitmentKeys[i].Basis) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key basis to GPU") + logger.Trace(log, "Pinning commitment key basis to GPU", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) pk.CommitmentKeysDevice.Basis[i], err = loadG1Raw(ckBasisHost) if err != nil { @@ -245,7 +248,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } if len(pk.CommitmentKeys[i].BasisExpSigma) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key BasisExpSigma to GPU") + logger.Trace(log, "Pinning commitment key BasisExpSigma to GPU", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) pk.CommitmentKeysDevice.BasisExpSigma[i], err = loadG1Raw(ckBasisExpSigmaHost) if err != nil { @@ -255,7 +258,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } - log.Info().Msg("All vectors pinned to GPU successfully") + log.Debug("All vectors pinned to GPU successfully") }) <-pinVectorsDone } @@ -325,7 +328,7 @@ func loadG1(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G1 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -338,7 +341,7 @@ func loadG1Raw(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Dev // NO conversion - keep Montgomery form for commitment keys if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (raw, Montgomery preserved)") + logger.Trace(log, "Loaded G1 vector (raw, Montgomery preserved)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -353,7 +356,7 @@ func loadG2(hostSlice icicle_core.HostSlice[curve.G2Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G2 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G2 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -790,7 +793,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "icicle").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) @@ -798,7 +801,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic needsSetup := pk.deviceInfo == nil pk.setupMu.Unlock() if needsSetup { - log.Debug().Msg("precomputing proving key in GPU") + logger.Trace(log, "precomputing proving key in GPU") } if err := pk.setupDevicePointers(&device); err != nil { return nil, fmt.Errorf("setup device pointers: %w", err) @@ -839,10 +842,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.Basis) && pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key basis for MSM") + logger.Trace(log, "Using pinned commitment key basis for MSM", slog.Int("commitment", i)) ckBasisDevice = pk.CommitmentKeysDevice.Basis[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key basis for MSM") + logger.Trace(log, "Loading commitment key basis for MSM", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) var err error ckBasisDevice, err = loadG1Raw(ckBasisHost) @@ -854,7 +857,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && ckBasisDevice.AsUnsafePointer() != nil { ckBasisDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key basis") + logger.Trace(log, "Freed commitment key basis", slog.Int("commitment", i)) } }() @@ -917,10 +920,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisExpSigmaDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.BasisExpSigma) && pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Using pinned commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaDevice = pk.CommitmentKeysDevice.BasisExpSigma[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Loading commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) var err error ckBasisExpSigmaDevice, err = loadG1Raw(ckBasisExpSigmaHost) @@ -938,7 +941,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic if shouldFree && ckBasisExpSigmaDevice.AsUnsafePointer() != nil { ckBasisExpSigmaDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key BasisExpSigma") + logger.Trace(log, "Freed commitment key BasisExpSigma", slog.Int("commitment", i)) } } close(ckBasisExpSigmaMsmBatchDone) @@ -955,11 +958,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic privateCommittedValuesDevice[i].Free() } } - log.Debug().Msg("Freed all privateCommittedValuesDevice after POK") + logger.Trace(log, "Freed all privateCommittedValuesDevice after POK") }) if isProfileMode { - log.Debug().Dur("took", time.Since(startPoKBatch)).Msg("ICICLE Batch Proof of Knowledge") + logger.Trace(log, "ICICLE Batch Proof of Knowledge", slog.Duration("took", time.Since(startPoKBatch))) } } // compute challenge for folding the PoKs from the commitments @@ -1056,11 +1059,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.B from GPU") + logger.Trace(log, "Using pinned G1.B from GPU") g1BDevice = pk.PinnedG1Device.B shouldFree = false } else { - log.Debug().Msg("Loading G1.B for BS1 MSM") + logger.Trace(log, "Loading G1.B for BS1 MSM") g1BHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.B) var err error g1BDevice, err = loadG1(g1BHost) @@ -1072,7 +1075,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1BDevice.AsUnsafePointer() != nil { g1BDevice.Free() - log.Debug().Msg("Freed G1.B after BS1 MSM") + logger.Trace(log, "Freed G1.B after BS1 MSM") } }() @@ -1086,11 +1089,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic bs1 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs1") } bs1.AddMixed(&pk.G1.Beta) @@ -1104,11 +1107,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.A.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.A from GPU") + logger.Trace(log, "Using pinned G1.A from GPU") g1ADevice = pk.PinnedG1Device.A shouldFree = false } else { - log.Debug().Msg("Loading G1.A for AR1 MSM") + logger.Trace(log, "Loading G1.A for AR1 MSM") g1AHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.A) var err error g1ADevice, err = loadG1(g1AHost) @@ -1120,7 +1123,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1ADevice.AsUnsafePointer() != nil { g1ADevice.Free() - log.Debug().Msg("Freed G1.A after AR1 MSM") + logger.Trace(log, "Freed G1.A after AR1 MSM") } }() @@ -1134,11 +1137,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic ar = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Ar1") } ar.AddMixed(&pk.G1.Alpha) @@ -1153,11 +1156,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFreeZ bool if pk.PinToGPU && pk.PinnedG1Device.Z.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.Z from GPU") + logger.Trace(log, "Using pinned G1.Z from GPU") g1ZDevice = pk.PinnedG1Device.Z shouldFreeZ = false } else { - log.Debug().Msg("Loading G1.Z for KRS MSM") + logger.Trace(log, "Loading G1.Z for KRS MSM") g1ZHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.Z) var err error g1ZDevice, err = loadG1(g1ZHost) @@ -1169,7 +1172,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeZ && g1ZDevice.AsUnsafePointer() != nil { g1ZDevice.Free() - log.Debug().Msg("Freed G1.Z after KRS MSM") + logger.Trace(log, "Freed G1.Z after KRS MSM") } }() @@ -1186,22 +1189,22 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs2 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs2") } var g1KDevice icicle_core.DeviceSlice var shouldFreeK bool if pk.PinToGPU && pk.PinnedG1Device.K.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.K from GPU") + logger.Trace(log, "Using pinned G1.K from GPU") g1KDevice = pk.PinnedG1Device.K shouldFreeK = false } else { - log.Debug().Msg("Loading G1.K for KRS MSM") + logger.Trace(log, "Loading G1.K for KRS MSM") g1KHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.K) var err error g1KDevice, err = loadG1(g1KHost) @@ -1213,7 +1216,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeK && g1KDevice.AsUnsafePointer() != nil { g1KDevice.Free() - log.Debug().Msg("Freed G1.K after KRS MSM") + logger.Trace(log, "Freed G1.K after KRS MSM") } }() @@ -1239,11 +1242,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs") } krs.AddMixed(&deltas[2]) @@ -1266,11 +1269,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG2Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G2.B from GPU") + logger.Trace(log, "Using pinned G2.B from GPU") g2BDevice = pk.PinnedG2Device.B shouldFree = false } else { - log.Debug().Msg("Loading G2.B for BS2 MSM") + logger.Trace(log, "Loading G2.B for BS2 MSM") g2BHost := (icicle_core.HostSlice[curve.G2Affine])(pk.G2.B) var err error g2BDevice, err = loadG2(g2BHost) @@ -1282,7 +1285,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g2BDevice.AsUnsafePointer() != nil { g2BDevice.Free() - log.Debug().Msg("Freed G2.B after BS2 MSM") + logger.Trace(log, "Freed G2.B after BS2 MSM") } }() @@ -1299,11 +1302,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic Bs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs2 G2") } deltaS.FromAffine(&pk.G2.Delta) @@ -1341,18 +1344,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic }) <-computeKrsDone - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesADevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesBDevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free h failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) } }) @@ -1428,7 +1431,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic icicle_ntt.Ntt(scalarsDevice, icicle_core.KForward, &cfg, scalarsDevice) icicle_runtime.SynchronizeStream(scalarsStream) if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: NTT + INTT") + logger.Trace(log, "computeH: NTT + INTT", slog.Duration("took", time.Since(start))) } channel <- scalarsDevice runtime.KeepAlive(scalars) // keep host buffer alive until the async copy/NTT completes @@ -1462,7 +1465,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("mul a den in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: vecOps") + logger.Trace(log, "computeH: vecOps", slog.Duration("took", time.Since(start))) } defer bDevice.Free() defer cDevice.Free() @@ -1475,14 +1478,14 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("ntt a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: INTT final") + logger.Trace(log, "computeH: INTT final", slog.Duration("took", time.Since(start))) } if err := icicle_bn254.FromMontgomery(aDevice); err != icicle_runtime.Success { panic(fmt.Sprintf("fromMontgomery a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(startTotal)).Msg("computeH: Total") + logger.Trace(log, "computeH: Total", slog.Duration("took", time.Since(startTotal))) } return aDevice } @@ -1503,47 +1506,47 @@ func (pk *ProvingKey) FreeGPUResources() { // Free pinned G1 vectors if pk.PinnedG1Device.A.AsUnsafePointer() != nil { pk.PinnedG1Device.A.Free() - log.Debug().Msg("Freed pinned G1.A") + logger.Trace(log, "Freed pinned G1.A") } if pk.PinnedG1Device.B.AsUnsafePointer() != nil { pk.PinnedG1Device.B.Free() - log.Debug().Msg("Freed pinned G1.B") + logger.Trace(log, "Freed pinned G1.B") } if pk.PinnedG1Device.K.AsUnsafePointer() != nil { pk.PinnedG1Device.K.Free() - log.Debug().Msg("Freed pinned G1.K") + logger.Trace(log, "Freed pinned G1.K") } if pk.PinnedG1Device.Z.AsUnsafePointer() != nil { pk.PinnedG1Device.Z.Free() - log.Debug().Msg("Freed pinned G1.Z") + logger.Trace(log, "Freed pinned G1.Z") } // Free pinned G2 vectors if pk.PinnedG2Device.B.AsUnsafePointer() != nil { pk.PinnedG2Device.B.Free() - log.Debug().Msg("Freed pinned G2.B") + logger.Trace(log, "Freed pinned G2.B") } // Free DenDevice if pk.DenDevice.AsUnsafePointer() != nil { pk.DenDevice.Free() - log.Debug().Msg("Freed DenDevice") + logger.Trace(log, "Freed DenDevice") } // Free pinned commitment keys for i := range pk.CommitmentKeysDevice.Basis { if pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.Basis[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key basis") + logger.Trace(log, "Freed pinned commitment key basis", slog.Int("commitment", i)) } } for i := range pk.CommitmentKeysDevice.BasisExpSigma { if pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.BasisExpSigma[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key BasisExpSigma") + logger.Trace(log, "Freed pinned commitment key BasisExpSigma", slog.Int("commitment", i)) } } - log.Info().Msg("All GPU resources freed") + log.Debug("All GPU resources freed") pk.deviceInfo = nil } diff --git a/backend/accelerated/icicle/groth16/bw6-761/icicle.go b/backend/accelerated/icicle/groth16/bw6-761/icicle.go index e557fee455..9c736ff334 100644 --- a/backend/accelerated/icicle/groth16/bw6-761/icicle.go +++ b/backend/accelerated/icicle/groth16/bw6-761/icicle.go @@ -20,6 +20,8 @@ import ( "time" "unsafe" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" curve "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" @@ -34,7 +36,8 @@ import ( cs "github.com/consensys/gnark/constraint/bw6-761" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/internal/logger" icicle_core "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/core" icicle_bw6761 "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/curves/bw6761" @@ -184,7 +187,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { /************************* Pin vectors to GPU if requested ***************************/ if pk.PinToGPU { log := logger.Logger() - log.Info().Msg("PinToGPU enabled - pre-loading all vectors to GPU memory") + log.Debug("PinToGPU enabled - pre-loading all vectors to GPU memory") pinVectorsDone := make(chan struct{}) icicle_runtime.RunOnDevice(device, func(args ...any) { @@ -193,7 +196,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { var err error // Pin G1.A - log.Debug().Msg("Pinning G1.A to GPU") + logger.Trace(log, "Pinning G1.A to GPU") g1AHost := icicle_core.HostSliceFromElements(pk.G1.A) pk.PinnedG1Device.A, err = loadG1(g1AHost) if err != nil { @@ -201,7 +204,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.B - log.Debug().Msg("Pinning G1.B to GPU") + logger.Trace(log, "Pinning G1.B to GPU") g1BHost := icicle_core.HostSliceFromElements(pk.G1.B) pk.PinnedG1Device.B, err = loadG1(g1BHost) if err != nil { @@ -209,7 +212,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.K - log.Debug().Msg("Pinning G1.K to GPU") + logger.Trace(log, "Pinning G1.K to GPU") g1KHost := icicle_core.HostSliceFromElements(pk.G1.K) pk.PinnedG1Device.K, err = loadG1(g1KHost) if err != nil { @@ -217,7 +220,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.Z - log.Debug().Msg("Pinning G1.Z to GPU") + logger.Trace(log, "Pinning G1.Z to GPU") g1ZHost := icicle_core.HostSliceFromElements(pk.G1.Z) pk.PinnedG1Device.Z, err = loadG1(g1ZHost) if err != nil { @@ -225,7 +228,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G2.B - log.Debug().Msg("Pinning G2.B to GPU") + logger.Trace(log, "Pinning G2.B to GPU") g2BHost := icicle_core.HostSliceFromElements(pk.G2.B) pk.PinnedG2Device.B, err = loadG2(g2BHost) if err != nil { @@ -237,7 +240,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { pk.CommitmentKeysDevice.BasisExpSigma = make([]icicle_core.DeviceSlice, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { if len(pk.CommitmentKeys[i].Basis) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key basis to GPU") + logger.Trace(log, "Pinning commitment key basis to GPU", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) pk.CommitmentKeysDevice.Basis[i], err = loadG1Raw(ckBasisHost) if err != nil { @@ -245,7 +248,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } if len(pk.CommitmentKeys[i].BasisExpSigma) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key BasisExpSigma to GPU") + logger.Trace(log, "Pinning commitment key BasisExpSigma to GPU", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) pk.CommitmentKeysDevice.BasisExpSigma[i], err = loadG1Raw(ckBasisExpSigmaHost) if err != nil { @@ -255,7 +258,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } - log.Info().Msg("All vectors pinned to GPU successfully") + log.Debug("All vectors pinned to GPU successfully") }) <-pinVectorsDone } @@ -314,7 +317,7 @@ func loadG1(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G1 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -327,7 +330,7 @@ func loadG1Raw(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Dev // NO conversion - keep Montgomery form for commitment keys if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (raw, Montgomery preserved)") + logger.Trace(log, "Loaded G1 vector (raw, Montgomery preserved)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -342,7 +345,7 @@ func loadG2(hostSlice icicle_core.HostSlice[curve.G2Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G2 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G2 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -779,7 +782,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "icicle").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) @@ -787,7 +790,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic needsSetup := pk.deviceInfo == nil pk.setupMu.Unlock() if needsSetup { - log.Debug().Msg("precomputing proving key in GPU") + logger.Trace(log, "precomputing proving key in GPU") } if err := pk.setupDevicePointers(&device); err != nil { return nil, fmt.Errorf("setup device pointers: %w", err) @@ -828,10 +831,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.Basis) && pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key basis for MSM") + logger.Trace(log, "Using pinned commitment key basis for MSM", slog.Int("commitment", i)) ckBasisDevice = pk.CommitmentKeysDevice.Basis[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key basis for MSM") + logger.Trace(log, "Loading commitment key basis for MSM", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) var err error ckBasisDevice, err = loadG1Raw(ckBasisHost) @@ -843,7 +846,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && ckBasisDevice.AsUnsafePointer() != nil { ckBasisDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key basis") + logger.Trace(log, "Freed commitment key basis", slog.Int("commitment", i)) } }() @@ -906,10 +909,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisExpSigmaDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.BasisExpSigma) && pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Using pinned commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaDevice = pk.CommitmentKeysDevice.BasisExpSigma[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Loading commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) var err error ckBasisExpSigmaDevice, err = loadG1Raw(ckBasisExpSigmaHost) @@ -927,7 +930,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic if shouldFree && ckBasisExpSigmaDevice.AsUnsafePointer() != nil { ckBasisExpSigmaDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key BasisExpSigma") + logger.Trace(log, "Freed commitment key BasisExpSigma", slog.Int("commitment", i)) } } close(ckBasisExpSigmaMsmBatchDone) @@ -944,11 +947,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic privateCommittedValuesDevice[i].Free() } } - log.Debug().Msg("Freed all privateCommittedValuesDevice after POK") + logger.Trace(log, "Freed all privateCommittedValuesDevice after POK") }) if isProfileMode { - log.Debug().Dur("took", time.Since(startPoKBatch)).Msg("ICICLE Batch Proof of Knowledge") + logger.Trace(log, "ICICLE Batch Proof of Knowledge", slog.Duration("took", time.Since(startPoKBatch))) } } // compute challenge for folding the PoKs from the commitments @@ -1045,11 +1048,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.B from GPU") + logger.Trace(log, "Using pinned G1.B from GPU") g1BDevice = pk.PinnedG1Device.B shouldFree = false } else { - log.Debug().Msg("Loading G1.B for BS1 MSM") + logger.Trace(log, "Loading G1.B for BS1 MSM") g1BHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.B) var err error g1BDevice, err = loadG1(g1BHost) @@ -1061,7 +1064,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1BDevice.AsUnsafePointer() != nil { g1BDevice.Free() - log.Debug().Msg("Freed G1.B after BS1 MSM") + logger.Trace(log, "Freed G1.B after BS1 MSM") } }() @@ -1075,11 +1078,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic bs1 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs1") } bs1.AddMixed(&pk.G1.Beta) @@ -1093,11 +1096,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.A.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.A from GPU") + logger.Trace(log, "Using pinned G1.A from GPU") g1ADevice = pk.PinnedG1Device.A shouldFree = false } else { - log.Debug().Msg("Loading G1.A for AR1 MSM") + logger.Trace(log, "Loading G1.A for AR1 MSM") g1AHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.A) var err error g1ADevice, err = loadG1(g1AHost) @@ -1109,7 +1112,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1ADevice.AsUnsafePointer() != nil { g1ADevice.Free() - log.Debug().Msg("Freed G1.A after AR1 MSM") + logger.Trace(log, "Freed G1.A after AR1 MSM") } }() @@ -1123,11 +1126,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic ar = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Ar1") } ar.AddMixed(&pk.G1.Alpha) @@ -1142,11 +1145,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFreeZ bool if pk.PinToGPU && pk.PinnedG1Device.Z.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.Z from GPU") + logger.Trace(log, "Using pinned G1.Z from GPU") g1ZDevice = pk.PinnedG1Device.Z shouldFreeZ = false } else { - log.Debug().Msg("Loading G1.Z for KRS MSM") + logger.Trace(log, "Loading G1.Z for KRS MSM") g1ZHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.Z) var err error g1ZDevice, err = loadG1(g1ZHost) @@ -1158,7 +1161,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeZ && g1ZDevice.AsUnsafePointer() != nil { g1ZDevice.Free() - log.Debug().Msg("Freed G1.Z after KRS MSM") + logger.Trace(log, "Freed G1.Z after KRS MSM") } }() @@ -1175,22 +1178,22 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs2 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs2") } var g1KDevice icicle_core.DeviceSlice var shouldFreeK bool if pk.PinToGPU && pk.PinnedG1Device.K.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.K from GPU") + logger.Trace(log, "Using pinned G1.K from GPU") g1KDevice = pk.PinnedG1Device.K shouldFreeK = false } else { - log.Debug().Msg("Loading G1.K for KRS MSM") + logger.Trace(log, "Loading G1.K for KRS MSM") g1KHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.K) var err error g1KDevice, err = loadG1(g1KHost) @@ -1202,7 +1205,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeK && g1KDevice.AsUnsafePointer() != nil { g1KDevice.Free() - log.Debug().Msg("Freed G1.K after KRS MSM") + logger.Trace(log, "Freed G1.K after KRS MSM") } }() @@ -1228,11 +1231,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs") } krs.AddMixed(&deltas[2]) @@ -1255,11 +1258,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG2Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G2.B from GPU") + logger.Trace(log, "Using pinned G2.B from GPU") g2BDevice = pk.PinnedG2Device.B shouldFree = false } else { - log.Debug().Msg("Loading G2.B for BS2 MSM") + logger.Trace(log, "Loading G2.B for BS2 MSM") g2BHost := (icicle_core.HostSlice[curve.G2Affine])(pk.G2.B) var err error g2BDevice, err = loadG2(g2BHost) @@ -1271,7 +1274,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g2BDevice.AsUnsafePointer() != nil { g2BDevice.Free() - log.Debug().Msg("Freed G2.B after BS2 MSM") + logger.Trace(log, "Freed G2.B after BS2 MSM") } }() @@ -1288,11 +1291,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic Bs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs2 G2") } deltaS.FromAffine(&pk.G2.Delta) @@ -1330,18 +1333,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic }) <-computeKrsDone - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesADevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesBDevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free h failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) } }) @@ -1417,7 +1420,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic icicle_ntt.Ntt(scalarsDevice, icicle_core.KForward, &cfg, scalarsDevice) icicle_runtime.SynchronizeStream(scalarsStream) if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: NTT + INTT") + logger.Trace(log, "computeH: NTT + INTT", slog.Duration("took", time.Since(start))) } channel <- scalarsDevice runtime.KeepAlive(scalars) // keep host buffer alive until the async copy/NTT completes @@ -1451,7 +1454,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("mul a den in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: vecOps") + logger.Trace(log, "computeH: vecOps", slog.Duration("took", time.Since(start))) } defer bDevice.Free() defer cDevice.Free() @@ -1464,14 +1467,14 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("ntt a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: INTT final") + logger.Trace(log, "computeH: INTT final", slog.Duration("took", time.Since(start))) } if err := icicle_bw6761.FromMontgomery(aDevice); err != icicle_runtime.Success { panic(fmt.Sprintf("fromMontgomery a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(startTotal)).Msg("computeH: Total") + logger.Trace(log, "computeH: Total", slog.Duration("took", time.Since(startTotal))) } return aDevice } @@ -1492,47 +1495,47 @@ func (pk *ProvingKey) FreeGPUResources() { // Free pinned G1 vectors if pk.PinnedG1Device.A.AsUnsafePointer() != nil { pk.PinnedG1Device.A.Free() - log.Debug().Msg("Freed pinned G1.A") + logger.Trace(log, "Freed pinned G1.A") } if pk.PinnedG1Device.B.AsUnsafePointer() != nil { pk.PinnedG1Device.B.Free() - log.Debug().Msg("Freed pinned G1.B") + logger.Trace(log, "Freed pinned G1.B") } if pk.PinnedG1Device.K.AsUnsafePointer() != nil { pk.PinnedG1Device.K.Free() - log.Debug().Msg("Freed pinned G1.K") + logger.Trace(log, "Freed pinned G1.K") } if pk.PinnedG1Device.Z.AsUnsafePointer() != nil { pk.PinnedG1Device.Z.Free() - log.Debug().Msg("Freed pinned G1.Z") + logger.Trace(log, "Freed pinned G1.Z") } // Free pinned G2 vectors if pk.PinnedG2Device.B.AsUnsafePointer() != nil { pk.PinnedG2Device.B.Free() - log.Debug().Msg("Freed pinned G2.B") + logger.Trace(log, "Freed pinned G2.B") } // Free DenDevice if pk.DenDevice.AsUnsafePointer() != nil { pk.DenDevice.Free() - log.Debug().Msg("Freed DenDevice") + logger.Trace(log, "Freed DenDevice") } // Free pinned commitment keys for i := range pk.CommitmentKeysDevice.Basis { if pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.Basis[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key basis") + logger.Trace(log, "Freed pinned commitment key basis", slog.Int("commitment", i)) } } for i := range pk.CommitmentKeysDevice.BasisExpSigma { if pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.BasisExpSigma[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key BasisExpSigma") + logger.Trace(log, "Freed pinned commitment key BasisExpSigma", slog.Int("commitment", i)) } } - log.Info().Msg("All GPU resources freed") + log.Debug("All GPU resources freed") pk.deviceInfo = nil } diff --git a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl index 559ea3b626..d11b001acb 100644 --- a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl +++ b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl @@ -27,7 +27,9 @@ import ( cs "github.com/consensys/gnark/constraint/{{ toLower .Curve }}" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" + "log/slog" + + "github.com/consensys/gnark/internal/logger" icicle_core "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/core" icicle_{{ .CurvePkg }} "github.com/ingonyama-zk/icicle-gnark/v3/wrappers/golang/curves/{{ .CurvePkg }}" @@ -177,7 +179,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { /************************* Pin vectors to GPU if requested ***************************/ if pk.PinToGPU { log := logger.Logger() - log.Info().Msg("PinToGPU enabled - pre-loading all vectors to GPU memory") + log.Debug("PinToGPU enabled - pre-loading all vectors to GPU memory") pinVectorsDone := make(chan struct{}) icicle_runtime.RunOnDevice(device, func(args ...any) { @@ -186,7 +188,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { var err error // Pin G1.A - log.Debug().Msg("Pinning G1.A to GPU") + logger.Trace(log, "Pinning G1.A to GPU") g1AHost := icicle_core.HostSliceFromElements(pk.G1.A) pk.PinnedG1Device.A, err = loadG1(g1AHost) if err != nil { @@ -194,7 +196,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.B - log.Debug().Msg("Pinning G1.B to GPU") + logger.Trace(log, "Pinning G1.B to GPU") g1BHost := icicle_core.HostSliceFromElements(pk.G1.B) pk.PinnedG1Device.B, err = loadG1(g1BHost) if err != nil { @@ -202,7 +204,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.K - log.Debug().Msg("Pinning G1.K to GPU") + logger.Trace(log, "Pinning G1.K to GPU") g1KHost := icicle_core.HostSliceFromElements(pk.G1.K) pk.PinnedG1Device.K, err = loadG1(g1KHost) if err != nil { @@ -210,7 +212,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G1.Z - log.Debug().Msg("Pinning G1.Z to GPU") + logger.Trace(log, "Pinning G1.Z to GPU") g1ZHost := icicle_core.HostSliceFromElements(pk.G1.Z) pk.PinnedG1Device.Z, err = loadG1(g1ZHost) if err != nil { @@ -218,7 +220,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } // Pin G2.B - log.Debug().Msg("Pinning G2.B to GPU") + logger.Trace(log, "Pinning G2.B to GPU") g2BHost := icicle_core.HostSliceFromElements(pk.G2.B) pk.PinnedG2Device.B, err = loadG2(g2BHost) if err != nil { @@ -230,7 +232,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { pk.CommitmentKeysDevice.BasisExpSigma = make([]icicle_core.DeviceSlice, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { if len(pk.CommitmentKeys[i].Basis) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key basis to GPU") + logger.Trace(log, "Pinning commitment key basis to GPU", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) pk.CommitmentKeysDevice.Basis[i], err = loadG1Raw(ckBasisHost) if err != nil { @@ -238,7 +240,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } if len(pk.CommitmentKeys[i].BasisExpSigma) > 0 { - log.Debug().Int("commitment", i).Msg("Pinning commitment key BasisExpSigma to GPU") + logger.Trace(log, "Pinning commitment key BasisExpSigma to GPU", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) pk.CommitmentKeysDevice.BasisExpSigma[i], err = loadG1Raw(ckBasisExpSigmaHost) if err != nil { @@ -248,7 +250,7 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { } } - log.Info().Msg("All vectors pinned to GPU successfully") + log.Debug("All vectors pinned to GPU successfully") }) <-pinVectorsDone } @@ -339,7 +341,7 @@ func loadG1(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G1 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -352,7 +354,7 @@ func loadG1Raw(hostSlice icicle_core.HostSlice[curve.G1Affine]) (icicle_core.Dev // NO conversion - keep Montgomery form for commitment keys if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G1 vector (raw, Montgomery preserved)") + logger.Trace(log, "Loaded G1 vector (raw, Montgomery preserved)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -367,7 +369,7 @@ func loadG2(hostSlice icicle_core.HostSlice[curve.G2Affine]) (icicle_core.Device } if isDebugMode { log := logger.Logger() - log.Debug().Int("size", deviceSlice.Len()).Msg("Loaded G2 vector (with Montgomery conversion)") + logger.Trace(log, "Loaded G2 vector (with Montgomery conversion)", slog.Int("size", deviceSlice.Len())) } return deviceSlice, nil } @@ -804,7 +806,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "icicle").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) @@ -812,7 +814,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic needsSetup := pk.deviceInfo == nil pk.setupMu.Unlock() if needsSetup { - log.Debug().Msg("precomputing proving key in GPU") + logger.Trace(log, "precomputing proving key in GPU") } if err := pk.setupDevicePointers(&device); err != nil { return nil, fmt.Errorf("setup device pointers: %w", err) @@ -853,10 +855,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.Basis) && pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key basis for MSM") + logger.Trace(log, "Using pinned commitment key basis for MSM", slog.Int("commitment", i)) ckBasisDevice = pk.CommitmentKeysDevice.Basis[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key basis for MSM") + logger.Trace(log, "Loading commitment key basis for MSM", slog.Int("commitment", i)) ckBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) var err error ckBasisDevice, err = loadG1Raw(ckBasisHost) @@ -868,7 +870,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && ckBasisDevice.AsUnsafePointer() != nil { ckBasisDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key basis") + logger.Trace(log, "Freed commitment key basis", slog.Int("commitment", i)) } }() @@ -931,10 +933,10 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var ckBasisExpSigmaDevice icicle_core.DeviceSlice shouldFree := false if pk.PinToGPU && i < len(pk.CommitmentKeysDevice.BasisExpSigma) && pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { - log.Debug().Int("commitment", i).Msg("Using pinned commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Using pinned commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaDevice = pk.CommitmentKeysDevice.BasisExpSigma[i] } else { - log.Debug().Int("commitment", i).Msg("Loading commitment key BasisExpSigma for POK MSM") + logger.Trace(log, "Loading commitment key BasisExpSigma for POK MSM", slog.Int("commitment", i)) ckBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) var err error ckBasisExpSigmaDevice, err = loadG1Raw(ckBasisExpSigmaHost) @@ -952,7 +954,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic if shouldFree && ckBasisExpSigmaDevice.AsUnsafePointer() != nil { ckBasisExpSigmaDevice.Free() - log.Debug().Int("commitment", i).Msg("Freed commitment key BasisExpSigma") + logger.Trace(log, "Freed commitment key BasisExpSigma", slog.Int("commitment", i)) } } close(ckBasisExpSigmaMsmBatchDone) @@ -969,11 +971,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic privateCommittedValuesDevice[i].Free() } } - log.Debug().Msg("Freed all privateCommittedValuesDevice after POK") + logger.Trace(log, "Freed all privateCommittedValuesDevice after POK") }) if isProfileMode { - log.Debug().Dur("took", time.Since(startPoKBatch)).Msg("ICICLE Batch Proof of Knowledge") + logger.Trace(log, "ICICLE Batch Proof of Knowledge", slog.Duration("took", time.Since(startPoKBatch))) } } // compute challenge for folding the PoKs from the commitments @@ -1070,11 +1072,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.B from GPU") + logger.Trace(log, "Using pinned G1.B from GPU") g1BDevice = pk.PinnedG1Device.B shouldFree = false } else { - log.Debug().Msg("Loading G1.B for BS1 MSM") + logger.Trace(log, "Loading G1.B for BS1 MSM") g1BHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.B) var err error g1BDevice, err = loadG1(g1BHost) @@ -1086,7 +1088,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1BDevice.AsUnsafePointer() != nil { g1BDevice.Free() - log.Debug().Msg("Freed G1.B after BS1 MSM") + logger.Trace(log, "Freed G1.B after BS1 MSM") } }() @@ -1100,11 +1102,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic bs1 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs1") } bs1.AddMixed(&pk.G1.Beta) @@ -1118,11 +1120,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG1Device.A.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.A from GPU") + logger.Trace(log, "Using pinned G1.A from GPU") g1ADevice = pk.PinnedG1Device.A shouldFree = false } else { - log.Debug().Msg("Loading G1.A for AR1 MSM") + logger.Trace(log, "Loading G1.A for AR1 MSM") g1AHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.A) var err error g1ADevice, err = loadG1(g1AHost) @@ -1134,7 +1136,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g1ADevice.AsUnsafePointer() != nil { g1ADevice.Free() - log.Debug().Msg("Freed G1.A after AR1 MSM") + logger.Trace(log, "Freed G1.A after AR1 MSM") } }() @@ -1148,11 +1150,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic ar = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Ar1") } ar.AddMixed(&pk.G1.Alpha) @@ -1167,11 +1169,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFreeZ bool if pk.PinToGPU && pk.PinnedG1Device.Z.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.Z from GPU") + logger.Trace(log, "Using pinned G1.Z from GPU") g1ZDevice = pk.PinnedG1Device.Z shouldFreeZ = false } else { - log.Debug().Msg("Loading G1.Z for KRS MSM") + logger.Trace(log, "Loading G1.Z for KRS MSM") g1ZHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.Z) var err error g1ZDevice, err = loadG1(g1ZHost) @@ -1183,7 +1185,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeZ && g1ZDevice.AsUnsafePointer() != nil { g1ZDevice.Free() - log.Debug().Msg("Freed G1.Z after KRS MSM") + logger.Trace(log, "Freed G1.Z after KRS MSM") } }() @@ -1200,22 +1202,22 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs2 = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs2") } var g1KDevice icicle_core.DeviceSlice var shouldFreeK bool if pk.PinToGPU && pk.PinnedG1Device.K.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G1.K from GPU") + logger.Trace(log, "Using pinned G1.K from GPU") g1KDevice = pk.PinnedG1Device.K shouldFreeK = false } else { - log.Debug().Msg("Loading G1.K for KRS MSM") + logger.Trace(log, "Loading G1.K for KRS MSM") g1KHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.K) var err error g1KDevice, err = loadG1(g1KHost) @@ -1227,7 +1229,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFreeK && g1KDevice.AsUnsafePointer() != nil { g1KDevice.Free() - log.Debug().Msg("Freed G1.K after KRS MSM") + logger.Trace(log, "Freed G1.K after KRS MSM") } }() @@ -1253,11 +1255,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic krs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Krs") } krs.AddMixed(&deltas[2]) @@ -1280,11 +1282,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic var shouldFree bool if pk.PinToGPU && pk.PinnedG2Device.B.AsUnsafePointer() != nil { - log.Debug().Msg("Using pinned G2.B from GPU") + logger.Trace(log, "Using pinned G2.B from GPU") g2BDevice = pk.PinnedG2Device.B shouldFree = false } else { - log.Debug().Msg("Loading G2.B for BS2 MSM") + logger.Trace(log, "Loading G2.B for BS2 MSM") g2BHost := (icicle_core.HostSlice[curve.G2Affine])(pk.G2.B) var err error g2BDevice, err = loadG2(g2BHost) @@ -1296,7 +1298,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic defer func() { if shouldFree && g2BDevice.AsUnsafePointer() != nil { g2BDevice.Free() - log.Debug().Msg("Freed G2.B after BS2 MSM") + logger.Trace(log, "Freed G2.B after BS2 MSM") } }() @@ -1313,11 +1315,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic Bs = jac if isProfileMode { - evt := log.Debug().Dur("took", time.Since(start)) if chunks > 1 { - evt = evt.Int("chunks", chunks) + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start)), slog.Int("chunks", chunks)) + } else { + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(start))) } - evt.Msg("MSM Bs2 G2") } deltaS.FromAffine(&pk.G2.Delta) @@ -1355,18 +1357,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic }) <-computeKrsDone - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesADevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free wireValuesBDevice failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error().Msgf("free h failed: %s", err.AsString()) + log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) } }) @@ -1442,7 +1444,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic icicle_ntt.Ntt(scalarsDevice, icicle_core.KForward, &cfg, scalarsDevice) icicle_runtime.SynchronizeStream(scalarsStream) if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: NTT + INTT") + logger.Trace(log, "computeH: NTT + INTT", slog.Duration("took", time.Since(start))) } channel <- scalarsDevice runtime.KeepAlive(scalars) // keep host buffer alive until the async copy/NTT completes @@ -1476,7 +1478,7 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("mul a den in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: vecOps") + logger.Trace(log, "computeH: vecOps", slog.Duration("took", time.Since(start))) } defer bDevice.Free() defer cDevice.Free() @@ -1489,14 +1491,14 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic panic(fmt.Sprintf("ntt a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("computeH: INTT final") + logger.Trace(log, "computeH: INTT final", slog.Duration("took", time.Since(start))) } if err := icicle_{{ .CurvePkg }}.FromMontgomery(aDevice); err != icicle_runtime.Success { panic(fmt.Sprintf("fromMontgomery a in computeH: %s", err.AsString())) } if isProfileMode { - log.Debug().Dur("took", time.Since(startTotal)).Msg("computeH: Total") + logger.Trace(log, "computeH: Total", slog.Duration("took", time.Since(startTotal))) } return aDevice } @@ -1517,47 +1519,47 @@ func (pk *ProvingKey) FreeGPUResources() { // Free pinned G1 vectors if pk.PinnedG1Device.A.AsUnsafePointer() != nil { pk.PinnedG1Device.A.Free() - log.Debug().Msg("Freed pinned G1.A") + logger.Trace(log, "Freed pinned G1.A") } if pk.PinnedG1Device.B.AsUnsafePointer() != nil { pk.PinnedG1Device.B.Free() - log.Debug().Msg("Freed pinned G1.B") + logger.Trace(log, "Freed pinned G1.B") } if pk.PinnedG1Device.K.AsUnsafePointer() != nil { pk.PinnedG1Device.K.Free() - log.Debug().Msg("Freed pinned G1.K") + logger.Trace(log, "Freed pinned G1.K") } if pk.PinnedG1Device.Z.AsUnsafePointer() != nil { pk.PinnedG1Device.Z.Free() - log.Debug().Msg("Freed pinned G1.Z") + logger.Trace(log, "Freed pinned G1.Z") } // Free pinned G2 vectors if pk.PinnedG2Device.B.AsUnsafePointer() != nil { pk.PinnedG2Device.B.Free() - log.Debug().Msg("Freed pinned G2.B") + logger.Trace(log, "Freed pinned G2.B") } // Free DenDevice if pk.DenDevice.AsUnsafePointer() != nil { pk.DenDevice.Free() - log.Debug().Msg("Freed DenDevice") + logger.Trace(log, "Freed DenDevice") } // Free pinned commitment keys for i := range pk.CommitmentKeysDevice.Basis { if pk.CommitmentKeysDevice.Basis[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.Basis[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key basis") + logger.Trace(log, "Freed pinned commitment key basis", slog.Int("commitment", i)) } } for i := range pk.CommitmentKeysDevice.BasisExpSigma { if pk.CommitmentKeysDevice.BasisExpSigma[i].AsUnsafePointer() != nil { pk.CommitmentKeysDevice.BasisExpSigma[i].Free() - log.Debug().Int("commitment", i).Msg("Freed pinned commitment key BasisExpSigma") + logger.Trace(log, "Freed pinned commitment key BasisExpSigma", slog.Int("commitment", i)) } } - log.Info().Msg("All GPU resources freed") + log.Debug("All GPU resources freed") pk.deviceInfo = nil } From 72b769b586caaf29bd35054ed45832224a99f25d Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Sun, 17 May 2026 22:55:59 +0000 Subject: [PATCH 07/44] feat: add backend options for providing logger --- backend/backend.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/backend/backend.go b/backend/backend.go index 5bc86fd142..b7637c0a78 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -8,8 +8,10 @@ import ( "crypto/sha256" "fmt" "hash" + "log/slog" "github.com/consensys/gnark/constraint/solver" + "github.com/consensys/gnark/internal/logger" ) // ID represent a unique ID for a proving scheme @@ -62,6 +64,7 @@ type ProverConfig struct { ChallengeHash hash.Hash KZGFoldingHash hash.Hash StatisticalZK bool + Logger *slog.Logger } // NewProverConfig returns a default ProverConfig with given prover options opts @@ -72,6 +75,7 @@ func NewProverConfig(opts ...ProverOption) (ProverConfig, error) { // separation tags for PLONK and Groth16 ChallengeHash: sha256.New(), KZGFoldingHash: sha256.New(), + Logger: logger.Logger(), } for _, option := range opts { if err := option(&opt); err != nil { @@ -81,6 +85,19 @@ func NewProverConfig(opts ...ProverOption) (ProverConfig, error) { return opt, nil } +// WithProverLogger sets the logger used by the prover and its internal solver. +// If this option is not provided, the default logger is used. Passing nil +// disables logging. +func WithProverLogger(log *slog.Logger) ProverOption { + return func(opt *ProverConfig) error { + if log == nil { + log = logger.DisabledLogger() + } + opt.Logger = log + return nil + } +} + // WithSolverOptions specifies the constraint system solver options. func WithSolverOptions(solverOpts ...solver.Option) ProverOption { return func(opt *ProverConfig) error { @@ -157,6 +174,8 @@ type VerifierConfig struct { HashToFieldFn hash.Hash ChallengeHash hash.Hash KZGFoldingHash hash.Hash + + Logger *slog.Logger } // NewVerifierConfig returns a default [VerifierConfig] with given verifier @@ -167,6 +186,7 @@ func NewVerifierConfig(opts ...VerifierOption) (VerifierConfig, error) { // separation tags for PLONK and Groth16 ChallengeHash: sha256.New(), KZGFoldingHash: sha256.New(), + Logger: logger.Logger(), } for _, option := range opts { if err := option(&opt); err != nil { @@ -208,3 +228,15 @@ func WithVerifierKZGFoldingHashFunction(hFunc hash.Hash) VerifierOption { return nil } } + +// WithVerifierLogger sets the logger used by the verifier. If this option is +// not provided, the default logger is used. Passing nil disables logging. +func WithVerifierLogger(log *slog.Logger) VerifierOption { + return func(vc *VerifierConfig) error { + if log == nil { + log = logger.DisabledLogger() + } + vc.Logger = log + return nil + } +} From 27db43e80fffffebdf224e20173e2733fd20b938 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Sun, 17 May 2026 22:57:42 +0000 Subject: [PATCH 08/44] fix: use provided logger for icicle backend --- backend/accelerated/icicle/groth16/bls12-377/icicle.go | 2 +- backend/accelerated/icicle/groth16/bls12-381/icicle.go | 2 +- backend/accelerated/icicle/groth16/bn254/icicle.go | 2 +- backend/accelerated/icicle/groth16/bw6-761/icicle.go | 2 +- .../icicle/internal/generator/templates/groth16.icicle.go.tmpl | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/accelerated/icicle/groth16/bls12-377/icicle.go b/backend/accelerated/icicle/groth16/bls12-377/icicle.go index bbecc58bf7..631e68f302 100644 --- a/backend/accelerated/icicle/groth16/bls12-377/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-377/icicle.go @@ -793,7 +793,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) diff --git a/backend/accelerated/icicle/groth16/bls12-381/icicle.go b/backend/accelerated/icicle/groth16/bls12-381/icicle.go index 0f52d0b66c..b3d2b09fa2 100644 --- a/backend/accelerated/icicle/groth16/bls12-381/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-381/icicle.go @@ -793,7 +793,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) diff --git a/backend/accelerated/icicle/groth16/bn254/icicle.go b/backend/accelerated/icicle/groth16/bn254/icicle.go index 2680cd8b00..3b64fe1ab8 100644 --- a/backend/accelerated/icicle/groth16/bn254/icicle.go +++ b/backend/accelerated/icicle/groth16/bn254/icicle.go @@ -793,7 +793,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) diff --git a/backend/accelerated/icicle/groth16/bw6-761/icicle.go b/backend/accelerated/icicle/groth16/bw6-761/icicle.go index 9c736ff334..8f49fb8638 100644 --- a/backend/accelerated/icicle/groth16/bw6-761/icicle.go +++ b/backend/accelerated/icicle/groth16/bw6-761/icicle.go @@ -782,7 +782,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) diff --git a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl index d11b001acb..d10e0cd65c 100644 --- a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl +++ b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl @@ -806,7 +806,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } pk.PinToGPU = cfg.PinToGPU - log := logger.Logger().With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "icicle"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) device := icicle_runtime.CreateDevice(cfg.Backend.String(), cfg.DeviceID) From c0850ecf1e8ee3b84af16cd156cb57a163a63a1f Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Sun, 17 May 2026 23:22:50 +0000 Subject: [PATCH 09/44] feat: use provided logger in backend prove/verify --- backend/groth16/bls12-377/prove.go | 17 ++++++++++------- backend/groth16/bls12-377/verify.go | 6 +++--- backend/groth16/bls12-381/prove.go | 17 ++++++++++------- backend/groth16/bls12-381/verify.go | 13 +++++++------ backend/groth16/bn254/prove.go | 17 ++++++++++------- backend/groth16/bn254/verify.go | 13 +++++++------ backend/groth16/bw6-761/prove.go | 17 ++++++++++------- backend/groth16/bw6-761/verify.go | 6 +++--- backend/plonk/bls12-377/prove.go | 16 ++++++++-------- backend/plonk/bls12-377/verify.go | 9 ++++----- backend/plonk/bls12-381/prove.go | 16 ++++++++-------- backend/plonk/bls12-381/verify.go | 9 ++++----- backend/plonk/bn254/prove.go | 16 ++++++++-------- backend/plonk/bn254/verify.go | 9 ++++----- backend/plonk/bw6-761/prove.go | 16 ++++++++-------- backend/plonk/bw6-761/verify.go | 9 ++++----- .../zkpschemes/groth16/groth16.prove.go.tmpl | 13 ++++++++----- .../zkpschemes/groth16/groth16.verify.go.tmpl | 13 +++++++------ .../zkpschemes/plonk/plonk.prove.go.tmpl | 15 ++++++++------- .../zkpschemes/plonk/plonk.verify.go.tmpl | 9 ++++----- 20 files changed, 135 insertions(+), 121 deletions(-) diff --git a/backend/groth16/bls12-377/prove.go b/backend/groth16/bls12-377/prove.go index 27071afbde..8f948b6b81 100644 --- a/backend/groth16/bls12-377/prove.go +++ b/backend/groth16/bls12-377/prove.go @@ -7,6 +7,7 @@ package groth16 import ( "fmt" + "log/slog" "math/big" "runtime" "time" @@ -16,14 +17,14 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/hash_to_field" + "github.com/consensys/gnark/constraint" + cs "github.com/consensys/gnark/constraint/bls12-377" + "github.com/consensys/gnark/internal/utils" + "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16/internal" "github.com/consensys/gnark/backend/witness" - "github.com/consensys/gnark/constraint" - cs "github.com/consensys/gnark/constraint/bls12-377" "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" fcs "github.com/consensys/gnark/frontend/cs" ) @@ -58,13 +59,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "none").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "none"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) proof := &Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) @@ -309,7 +312,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return proof, nil } diff --git a/backend/groth16/bls12-377/verify.go b/backend/groth16/bls12-377/verify.go index 0a6cab40cd..dd5541177d 100644 --- a/backend/groth16/bls12-377/verify.go +++ b/backend/groth16/bls12-377/verify.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "time" "github.com/consensys/gnark-crypto/ecc" @@ -19,7 +20,6 @@ import ( "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint" - "github.com/consensys/gnark/logger" ) var ( @@ -50,7 +50,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if len(publicWitness) != nbPublicVars-1 { return fmt.Errorf("invalid witness size, got %d, expected %d (public - ONE_WIRE)", len(publicWitness), len(vk.G1.K)-1) } - log := logger.Logger().With().Str("curve", vk.CurveID().String()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", vk.CurveID().String()), slog.String("backend", "groth16")) start := time.Now() // check that the points in the proof are in the correct subgroup @@ -133,7 +133,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac return errPairingCheckFailed } - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return nil } diff --git a/backend/groth16/bls12-381/prove.go b/backend/groth16/bls12-381/prove.go index c9e267ede3..d56f13c205 100644 --- a/backend/groth16/bls12-381/prove.go +++ b/backend/groth16/bls12-381/prove.go @@ -7,6 +7,7 @@ package groth16 import ( "fmt" + "log/slog" "math/big" "runtime" "time" @@ -16,14 +17,14 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/hash_to_field" + "github.com/consensys/gnark/constraint" + cs "github.com/consensys/gnark/constraint/bls12-381" + "github.com/consensys/gnark/internal/utils" + "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16/internal" "github.com/consensys/gnark/backend/witness" - "github.com/consensys/gnark/constraint" - cs "github.com/consensys/gnark/constraint/bls12-381" "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" fcs "github.com/consensys/gnark/frontend/cs" ) @@ -58,13 +59,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "none").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "none"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) proof := &Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) @@ -309,7 +312,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return proof, nil } diff --git a/backend/groth16/bls12-381/verify.go b/backend/groth16/bls12-381/verify.go index 28d3d90f75..c151e1ccc7 100644 --- a/backend/groth16/bls12-381/verify.go +++ b/backend/groth16/bls12-381/verify.go @@ -11,11 +11,13 @@ import ( "errors" "fmt" "io" + "log/slog" "math/big" "text/template" "time" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark/internal/logger" "golang.org/x/crypto/sha3" "github.com/consensys/gnark-crypto/ecc" @@ -26,7 +28,6 @@ import ( "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint" - "github.com/consensys/gnark/logger" ) var ( @@ -57,7 +58,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if len(publicWitness) != nbPublicVars-1 { return fmt.Errorf("invalid witness size, got %d, expected %d (public - ONE_WIRE)", len(publicWitness), len(vk.G1.K)-1) } - log := logger.Logger().With().Str("curve", vk.CurveID().String()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", vk.CurveID().String()), slog.String("backend", "groth16")) start := time.Now() // check that the points in the proof are in the correct subgroup @@ -140,7 +141,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac return errPairingCheckFailed } - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return nil } @@ -157,7 +158,7 @@ func (vk *VerifyingKey) ExportSolidity(w io.Writer, exportOpts ...solidity.Expor if cfg.HashToFieldFn == nil { // set the target hash function to legacy keccak256 as it is the default for `solidity.WithTargetSolidityVerifier`` cfg.HashToFieldFn = sha3.NewLegacyKeccak256() - log.Debug().Msg("hash to field function not set, using keccak256 as default") + log.Debug("hash to field function not set, using keccak256 as default") } // a bit hacky way to understand what hash function is provided. We already // receive instance of hash function but it is difficult to compare it with @@ -215,9 +216,9 @@ func (vk *VerifyingKey) ExportSolidity(w io.Writer, exportOpts ...solidity.Expor } if len(vk.PublicAndCommitmentCommitted) > 1 { - log.Warn().Msg("exporting solidity verifier with more than one commitment is not supported") + log.Warn("exporting solidity verifier with more than one commitment is not supported") } else if len(vk.PublicAndCommitmentCommitted) == 1 { - log.Warn().Msg("exporting solidity verifier only supports `sha256` as `HashToField`. The generated contract may not work for proofs generated with other hash functions.") + log.Warn("exporting solidity verifier only supports `sha256` as `HashToField`. The generated contract may not work for proofs generated with other hash functions.") } tmpl, err := template.New("").Funcs(helpers).Parse(solidityTemplate) diff --git a/backend/groth16/bn254/prove.go b/backend/groth16/bn254/prove.go index 57f52af95f..8dc176150d 100644 --- a/backend/groth16/bn254/prove.go +++ b/backend/groth16/bn254/prove.go @@ -7,6 +7,7 @@ package groth16 import ( "fmt" + "log/slog" "math/big" "runtime" "time" @@ -16,14 +17,14 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" "github.com/consensys/gnark-crypto/ecc/bn254/fr/hash_to_field" + "github.com/consensys/gnark/constraint" + cs "github.com/consensys/gnark/constraint/bn254" + "github.com/consensys/gnark/internal/utils" + "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16/internal" "github.com/consensys/gnark/backend/witness" - "github.com/consensys/gnark/constraint" - cs "github.com/consensys/gnark/constraint/bn254" "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" fcs "github.com/consensys/gnark/frontend/cs" ) @@ -58,13 +59,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "none").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "none"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) proof := &Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) @@ -309,7 +312,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return proof, nil } diff --git a/backend/groth16/bn254/verify.go b/backend/groth16/bn254/verify.go index 804d295a71..cad3064d54 100644 --- a/backend/groth16/bn254/verify.go +++ b/backend/groth16/bn254/verify.go @@ -11,11 +11,13 @@ import ( "errors" "fmt" "io" + "log/slog" "math/big" "text/template" "time" "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark/internal/logger" "golang.org/x/crypto/sha3" "github.com/consensys/gnark-crypto/ecc" @@ -26,7 +28,6 @@ import ( "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint" - "github.com/consensys/gnark/logger" ) var ( @@ -57,7 +58,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if len(publicWitness) != nbPublicVars-1 { return fmt.Errorf("invalid witness size, got %d, expected %d (public - ONE_WIRE)", len(publicWitness), len(vk.G1.K)-1) } - log := logger.Logger().With().Str("curve", vk.CurveID().String()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", vk.CurveID().String()), slog.String("backend", "groth16")) start := time.Now() // check that the points in the proof are in the correct subgroup @@ -140,7 +141,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac return errPairingCheckFailed } - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return nil } @@ -157,7 +158,7 @@ func (vk *VerifyingKey) ExportSolidity(w io.Writer, exportOpts ...solidity.Expor if cfg.HashToFieldFn == nil { // set the target hash function to legacy keccak256 as it is the default for `solidity.WithTargetSolidityVerifier`` cfg.HashToFieldFn = sha3.NewLegacyKeccak256() - log.Debug().Msg("hash to field function not set, using keccak256 as default") + log.Debug("hash to field function not set, using keccak256 as default") } // a bit hacky way to understand what hash function is provided. We already // receive instance of hash function but it is difficult to compare it with @@ -206,9 +207,9 @@ func (vk *VerifyingKey) ExportSolidity(w io.Writer, exportOpts ...solidity.Expor } if len(vk.PublicAndCommitmentCommitted) > 1 { - log.Warn().Msg("exporting solidity verifier with more than one commitment is not supported") + log.Warn("exporting solidity verifier with more than one commitment is not supported") } else if len(vk.PublicAndCommitmentCommitted) == 1 { - log.Warn().Msg("exporting solidity verifier only supports `sha256` as `HashToField`. The generated contract may not work for proofs generated with other hash functions.") + log.Warn("exporting solidity verifier only supports `sha256` as `HashToField`. The generated contract may not work for proofs generated with other hash functions.") } tmpl, err := template.New("").Funcs(helpers).Parse(solidityTemplate) diff --git a/backend/groth16/bw6-761/prove.go b/backend/groth16/bw6-761/prove.go index 396928f44f..2c4671e4bc 100644 --- a/backend/groth16/bw6-761/prove.go +++ b/backend/groth16/bw6-761/prove.go @@ -7,6 +7,7 @@ package groth16 import ( "fmt" + "log/slog" "math/big" "runtime" "time" @@ -16,14 +17,14 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/fft" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/hash_to_field" + "github.com/consensys/gnark/constraint" + cs "github.com/consensys/gnark/constraint/bw6-761" + "github.com/consensys/gnark/internal/utils" + "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16/internal" "github.com/consensys/gnark/backend/witness" - "github.com/consensys/gnark/constraint" - cs "github.com/consensys/gnark/constraint/bw6-761" "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" fcs "github.com/consensys/gnark/frontend/cs" ) @@ -58,13 +59,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "none").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "none"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) proof := &Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) @@ -309,7 +312,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return proof, nil } diff --git a/backend/groth16/bw6-761/verify.go b/backend/groth16/bw6-761/verify.go index e2d3d2ae2e..0ca50e0f37 100644 --- a/backend/groth16/bw6-761/verify.go +++ b/backend/groth16/bw6-761/verify.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "time" "github.com/consensys/gnark-crypto/ecc" @@ -19,7 +20,6 @@ import ( "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint" - "github.com/consensys/gnark/logger" ) var ( @@ -50,7 +50,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if len(publicWitness) != nbPublicVars-1 { return fmt.Errorf("invalid witness size, got %d, expected %d (public - ONE_WIRE)", len(publicWitness), len(vk.G1.K)-1) } - log := logger.Logger().With().Str("curve", vk.CurveID().String()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", vk.CurveID().String()), slog.String("backend", "groth16")) start := time.Now() // check that the points in the proof are in the correct subgroup @@ -133,7 +133,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac return errPairingCheckFailed } - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return nil } diff --git a/backend/plonk/bls12-377/prove.go b/backend/plonk/bls12-377/prove.go index 75e1414613..c34ea776f9 100644 --- a/backend/plonk/bls12-377/prove.go +++ b/backend/plonk/bls12-377/prove.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "hash" + "log/slog" "math/big" "math/bits" "runtime" @@ -38,7 +39,6 @@ import ( "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" ) const ( @@ -97,17 +97,14 @@ type Proof struct { func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...backend.ProverOption) (*Proof, error) { - log := logger.Logger().With(). - Str("curve", spr.CurveID().String()). - Int("nbConstraints", spr.GetNbConstraints()). - Str("backend", "plonk").Logger() - // parse the options opt, err := backend.NewProverConfig(opts...) if err != nil { return nil, fmt.Errorf("get prover options: %w", err) } + log := opt.Logger.With(slog.String("curve", spr.CurveID().String()), slog.Int("nbConstraints", spr.GetNbConstraints()), slog.String("backend", "plonk")) + start := time.Now() // init instance @@ -148,7 +145,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return instance.proof, nil } @@ -317,7 +314,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { - _solution, err := s.spr.Solve(s.fullWitness, s.opt.SolverOpts...) + solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) + solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) + solverOpts = append(solverOpts, s.opt.SolverOpts...) + _solution, err := s.spr.Solve(s.fullWitness, solverOpts...) if err != nil { return err } diff --git a/backend/plonk/bls12-377/verify.go b/backend/plonk/bls12-377/verify.go index c3bf19fde9..8b70b262d8 100644 --- a/backend/plonk/bls12-377/verify.go +++ b/backend/plonk/bls12-377/verify.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "math/big" "time" @@ -22,7 +23,6 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/kzg" fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir" "github.com/consensys/gnark/backend" - "github.com/consensys/gnark/logger" ) var ( @@ -32,13 +32,12 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...backend.VerifierOption) error { - - log := logger.Logger().With().Str("curve", "bls12-377").Str("backend", "plonk").Logger() - start := time.Now() cfg, err := backend.NewVerifierConfig(opts...) if err != nil { return fmt.Errorf("create backend config: %w", err) } + log := cfg.Logger.With(slog.String("curve", "bls12-377"), slog.String("backend", "plonk")) + start := time.Now() if len(proof.Bsb22Commitments) != len(vk.Qcp) { return errors.New("BSB22 Commitment number mismatch") @@ -307,7 +306,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac vk.Kzg, ) - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return err } diff --git a/backend/plonk/bls12-381/prove.go b/backend/plonk/bls12-381/prove.go index 67a8aac65d..2ca5a6cd77 100644 --- a/backend/plonk/bls12-381/prove.go +++ b/backend/plonk/bls12-381/prove.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "hash" + "log/slog" "math/big" "math/bits" "runtime" @@ -38,7 +39,6 @@ import ( "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" ) const ( @@ -97,17 +97,14 @@ type Proof struct { func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...backend.ProverOption) (*Proof, error) { - log := logger.Logger().With(). - Str("curve", spr.CurveID().String()). - Int("nbConstraints", spr.GetNbConstraints()). - Str("backend", "plonk").Logger() - // parse the options opt, err := backend.NewProverConfig(opts...) if err != nil { return nil, fmt.Errorf("get prover options: %w", err) } + log := opt.Logger.With(slog.String("curve", spr.CurveID().String()), slog.Int("nbConstraints", spr.GetNbConstraints()), slog.String("backend", "plonk")) + start := time.Now() // init instance @@ -148,7 +145,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return instance.proof, nil } @@ -317,7 +314,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { - _solution, err := s.spr.Solve(s.fullWitness, s.opt.SolverOpts...) + solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) + solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) + solverOpts = append(solverOpts, s.opt.SolverOpts...) + _solution, err := s.spr.Solve(s.fullWitness, solverOpts...) if err != nil { return err } diff --git a/backend/plonk/bls12-381/verify.go b/backend/plonk/bls12-381/verify.go index 985010b2fb..02e85dde6d 100644 --- a/backend/plonk/bls12-381/verify.go +++ b/backend/plonk/bls12-381/verify.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "math/big" "text/template" "time" @@ -22,7 +23,6 @@ import ( fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir" "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/solidity" - "github.com/consensys/gnark/logger" ) var ( @@ -32,13 +32,12 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...backend.VerifierOption) error { - - log := logger.Logger().With().Str("curve", "bls12-381").Str("backend", "plonk").Logger() - start := time.Now() cfg, err := backend.NewVerifierConfig(opts...) if err != nil { return fmt.Errorf("create backend config: %w", err) } + log := cfg.Logger.With(slog.String("curve", "bls12-381"), slog.String("backend", "plonk")) + start := time.Now() if len(proof.Bsb22Commitments) != len(vk.Qcp) { return errors.New("BSB22 Commitment number mismatch") @@ -307,7 +306,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac vk.Kzg, ) - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return err } diff --git a/backend/plonk/bn254/prove.go b/backend/plonk/bn254/prove.go index 2c788e8569..fca5f43949 100644 --- a/backend/plonk/bn254/prove.go +++ b/backend/plonk/bn254/prove.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "hash" + "log/slog" "math/big" "math/bits" "runtime" @@ -38,7 +39,6 @@ import ( "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" ) const ( @@ -97,17 +97,14 @@ type Proof struct { func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...backend.ProverOption) (*Proof, error) { - log := logger.Logger().With(). - Str("curve", spr.CurveID().String()). - Int("nbConstraints", spr.GetNbConstraints()). - Str("backend", "plonk").Logger() - // parse the options opt, err := backend.NewProverConfig(opts...) if err != nil { return nil, fmt.Errorf("get prover options: %w", err) } + log := opt.Logger.With(slog.String("curve", spr.CurveID().String()), slog.Int("nbConstraints", spr.GetNbConstraints()), slog.String("backend", "plonk")) + start := time.Now() // init instance @@ -148,7 +145,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return instance.proof, nil } @@ -317,7 +314,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { - _solution, err := s.spr.Solve(s.fullWitness, s.opt.SolverOpts...) + solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) + solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) + solverOpts = append(solverOpts, s.opt.SolverOpts...) + _solution, err := s.spr.Solve(s.fullWitness, solverOpts...) if err != nil { return err } diff --git a/backend/plonk/bn254/verify.go b/backend/plonk/bn254/verify.go index 4539008726..ac779616b0 100644 --- a/backend/plonk/bn254/verify.go +++ b/backend/plonk/bn254/verify.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "math/big" "text/template" "time" @@ -22,7 +23,6 @@ import ( fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir" "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/solidity" - "github.com/consensys/gnark/logger" ) var ( @@ -32,13 +32,12 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...backend.VerifierOption) error { - - log := logger.Logger().With().Str("curve", "bn254").Str("backend", "plonk").Logger() - start := time.Now() cfg, err := backend.NewVerifierConfig(opts...) if err != nil { return fmt.Errorf("create backend config: %w", err) } + log := cfg.Logger.With(slog.String("curve", "bn254"), slog.String("backend", "plonk")) + start := time.Now() if len(proof.Bsb22Commitments) != len(vk.Qcp) { return errors.New("BSB22 Commitment number mismatch") @@ -307,7 +306,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac vk.Kzg, ) - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return err } diff --git a/backend/plonk/bw6-761/prove.go b/backend/plonk/bw6-761/prove.go index 0a50efcb7c..063db7a26c 100644 --- a/backend/plonk/bw6-761/prove.go +++ b/backend/plonk/bw6-761/prove.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "hash" + "log/slog" "math/big" "math/bits" "runtime" @@ -38,7 +39,6 @@ import ( "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" ) const ( @@ -97,17 +97,14 @@ type Proof struct { func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...backend.ProverOption) (*Proof, error) { - log := logger.Logger().With(). - Str("curve", spr.CurveID().String()). - Int("nbConstraints", spr.GetNbConstraints()). - Str("backend", "plonk").Logger() - // parse the options opt, err := backend.NewProverConfig(opts...) if err != nil { return nil, fmt.Errorf("get prover options: %w", err) } + log := opt.Logger.With(slog.String("curve", spr.CurveID().String()), slog.Int("nbConstraints", spr.GetNbConstraints()), slog.String("backend", "plonk")) + start := time.Now() // init instance @@ -148,7 +145,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return instance.proof, nil } @@ -317,7 +314,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { - _solution, err := s.spr.Solve(s.fullWitness, s.opt.SolverOpts...) + solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) + solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) + solverOpts = append(solverOpts, s.opt.SolverOpts...) + _solution, err := s.spr.Solve(s.fullWitness, solverOpts...) if err != nil { return err } diff --git a/backend/plonk/bw6-761/verify.go b/backend/plonk/bw6-761/verify.go index 0aa5592eff..4a458da201 100644 --- a/backend/plonk/bw6-761/verify.go +++ b/backend/plonk/bw6-761/verify.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "math/big" "time" @@ -22,7 +23,6 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761/kzg" fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir" "github.com/consensys/gnark/backend" - "github.com/consensys/gnark/logger" ) var ( @@ -32,13 +32,12 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...backend.VerifierOption) error { - - log := logger.Logger().With().Str("curve", "bw6-761").Str("backend", "plonk").Logger() - start := time.Now() cfg, err := backend.NewVerifierConfig(opts...) if err != nil { return fmt.Errorf("create backend config: %w", err) } + log := cfg.Logger.With(slog.String("curve", "bw6-761"), slog.String("backend", "plonk")) + start := time.Now() if len(proof.Bsb22Commitments) != len(vk.Qcp) { return errors.New("BSB22 Commitment number mismatch") @@ -307,7 +306,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac vk.Kzg, ) - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return err } diff --git a/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl index b94532519c..9e7f45e444 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl @@ -12,12 +12,13 @@ import ( "github.com/consensys/gnark/constraint" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/internal/utils" + "log/slog" + "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16/internal" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/backend/witness" - "github.com/consensys/gnark/logger" - + fcs "github.com/consensys/gnark/frontend/cs" ) @@ -52,13 +53,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b opt.HashToFieldFn = hash_to_field.New([]byte(constraint.CommitmentDst)) } - log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "none").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", r1cs.CurveID().String()), slog.String("acceleration", "none"), slog.Int("nbConstraints", r1cs.GetNbConstraints()), slog.String("backend", "groth16")) commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) proof := &Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) @@ -303,7 +306,7 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return proof, nil } diff --git a/internal/generator/backend/template/zkpschemes/groth16/groth16.verify.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/groth16.verify.go.tmpl index f19a280edd..16befdc7c1 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/groth16.verify.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/groth16.verify.go.tmpl @@ -2,6 +2,7 @@ import ( "errors" "fmt" "io" + "log/slog" {{- if or (eq .Curve "BN254") (eq .Curve "BLS12-381") }} "math/big" "text/template" @@ -9,6 +10,7 @@ import ( "crypto/sha256" "golang.org/x/crypto/sha3" {{- template "import_fp" . }} + "github.com/consensys/gnark/internal/logger" {{- end}} "time" @@ -20,7 +22,6 @@ import ( "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint" - "github.com/consensys/gnark/logger" ) var ( @@ -51,7 +52,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if len(publicWitness) != nbPublicVars-1 { return fmt.Errorf("invalid witness size, got %d, expected %d (public - ONE_WIRE)", len(publicWitness), len(vk.G1.K) - 1) } - log := logger.Logger().With().Str("curve", vk.CurveID().String()).Str("backend", "groth16").Logger() + log := opt.Logger.With(slog.String("curve", vk.CurveID().String()), slog.String("backend", "groth16")) start := time.Now() // check that the points in the proof are in the correct subgroup @@ -134,7 +135,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac return errPairingCheckFailed } - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return nil } @@ -153,7 +154,7 @@ func (vk *VerifyingKey) ExportSolidity(w io.Writer, exportOpts ...solidity.Expor if cfg.HashToFieldFn == nil { // set the target hash function to legacy keccak256 as it is the default for `solidity.WithTargetSolidityVerifier`` cfg.HashToFieldFn = sha3.NewLegacyKeccak256() - log.Debug().Msg("hash to field function not set, using keccak256 as default") + log.Debug("hash to field function not set, using keccak256 as default") } // a bit hacky way to understand what hash function is provided. We already // receive instance of hash function but it is difficult to compare it with @@ -219,9 +220,9 @@ func (vk *VerifyingKey) ExportSolidity(w io.Writer, exportOpts ...solidity.Expor } if len(vk.PublicAndCommitmentCommitted) > 1 { - log.Warn().Msg("exporting solidity verifier with more than one commitment is not supported") + log.Warn("exporting solidity verifier with more than one commitment is not supported") } else if len(vk.PublicAndCommitmentCommitted) == 1 { - log.Warn().Msg("exporting solidity verifier only supports `sha256` as `HashToField`. The generated contract may not work for proofs generated with other hash functions.") + log.Warn("exporting solidity verifier only supports `sha256` as `HashToField`. The generated contract may not work for proofs generated with other hash functions.") } tmpl, err := template.New("").Funcs(helpers).Parse(solidityTemplate) diff --git a/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl b/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl index 47d201ad2a..f5d8764061 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl @@ -3,6 +3,7 @@ import ( "errors" "fmt" "hash" + "log/slog" "math/big" "math/bits" "runtime" @@ -25,7 +26,6 @@ import ( "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" fcs "github.com/consensys/gnark/frontend/cs" ) @@ -85,10 +85,6 @@ type Proof struct { func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...backend.ProverOption) (*Proof, error) { - log := logger.Logger().With(). - Str("curve", spr.CurveID().String()). - Int("nbConstraints", spr.GetNbConstraints()). - Str("backend", "plonk").Logger() // parse the options opt, err := backend.NewProverConfig(opts...) @@ -96,6 +92,8 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts return nil, fmt.Errorf("get prover options: %w", err) } + log := opt.Logger.With(slog.String("curve", spr.CurveID().String()), slog.Int("nbConstraints", spr.GetNbConstraints()), slog.String("backend", "plonk")) + start := time.Now() // init instance @@ -136,7 +134,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("prover done") + log.Debug("prover done", slog.Duration("took", time.Since(start))) return instance.proof, nil } @@ -305,7 +303,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { - _solution, err := s.spr.Solve(s.fullWitness, s.opt.SolverOpts...) + solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) + solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) + solverOpts = append(solverOpts, s.opt.SolverOpts...) + _solution, err := s.spr.Solve(s.fullWitness, solverOpts...) if err != nil { return err } diff --git a/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl b/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl index c2daa52500..f1795f8a6c 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl @@ -3,6 +3,7 @@ import ( "fmt" "io" "math/big" + "log/slog" {{ if or (eq .Curve "BN254") (eq .Curve "BLS12-381") -}} "text/template" {{- end }} @@ -19,7 +20,6 @@ import ( {{- template "import_kzg" . }} fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir" "github.com/consensys/gnark/backend" - "github.com/consensys/gnark/logger" ) var ( @@ -29,13 +29,12 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...backend.VerifierOption) error { - - log := logger.Logger().With().Str("curve", "{{ toLower .Curve }}").Str("backend", "plonk").Logger() - start := time.Now() cfg, err := backend.NewVerifierConfig(opts...) if err != nil { return fmt.Errorf("create backend config: %w", err) } + log := cfg.Logger.With(slog.String("curve", "{{ toLower .Curve }}"), slog.String("backend", "plonk")) + start := time.Now() if len(proof.Bsb22Commitments) != len(vk.Qcp) { return errors.New("BSB22 Commitment number mismatch") @@ -304,7 +303,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac vk.Kzg, ) - log.Debug().Dur("took", time.Since(start)).Msg("verifier done") + log.Debug("verifier done", slog.Duration("took", time.Since(start))) return err } From 45d109f0c794c3b64ee522ab39322d75421103a6 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 18 May 2026 08:36:08 +0000 Subject: [PATCH 10/44] feat: add backwards-compatible logger override in solver --- constraint/solver/options.go | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/constraint/solver/options.go b/constraint/solver/options.go index adbc9aaff6..9856b4f6e5 100644 --- a/constraint/solver/options.go +++ b/constraint/solver/options.go @@ -2,10 +2,10 @@ package solver import ( "fmt" + "log/slog" "runtime" - "github.com/consensys/gnark/logger" - "github.com/rs/zerolog" + "github.com/consensys/gnark/internal/logger" ) // Option defines option for altering the behavior of a constraint system @@ -16,7 +16,7 @@ type Option func(*Config) error // Config is the configuration for the solver with the options applied. type Config struct { HintFunctions map[HintID]Hint // defaults to all built-in hint functions - Logger zerolog.Logger // defaults to gnark.Logger + Logger *slog.Logger // defaults to gnark's internal logger NbTasks int // defaults to runtime.NumCPU() } @@ -47,12 +47,23 @@ func OverrideHint(id HintID, f Hint) Option { } } -// WithLogger is a prover option that specifies zerolog.Logger as a destination for the -// logs printed by api.Println(). By default, uses gnark/logger. -// zerolog.Nop() will disable logging -func WithLogger(l zerolog.Logger) Option { +// WithLogger specifies the destination for logs printed by api.Println(). It +// accepts *slog.Logger. For compatibility, legacy logger values are also +// accepted, but deprecated. If this option is not provided, the default logger +// is used. Passing nil disables logging. +// +// The deprecated zerolog type parameter is accepted for backward compatibility, +// but the user should prefer using slog.Logger directly, as it is the standard +// library logger in Go 1.21 and later, and it is the default logger used by +// gnark. The zerolog support may be removed in future versions. +func WithLogger[T logger.SlogAdapter](l T) Option { return func(opt *Config) error { - opt.Logger = l + log, ok := logger.AsSlog(l) + if ok { + opt.Logger = log + } else { + opt.Logger = logger.DisabledLogger() + } return nil } } @@ -81,8 +92,7 @@ func WithNbTasks(nbTasks int) Option { // NewConfig returns a default SolverConfig with given prover options opts applied. func NewConfig(opts ...Option) (Config, error) { - log := logger.Logger() - opt := Config{Logger: log} + opt := Config{Logger: logger.Logger()} opt.HintFunctions = cloneHintRegistry() opt.NbTasks = runtime.NumCPU() for _, option := range opts { From 8f50df71f8bcfd473b5ed5c8e66e3a674c4fcd0e Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 18 May 2026 08:40:07 +0000 Subject: [PATCH 11/44] chore: reduce log level for multiple hint registration --- constraint/solver/hint_registry.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/constraint/solver/hint_registry.go b/constraint/solver/hint_registry.go index 6aa6a3266d..02a34cb182 100644 --- a/constraint/solver/hint_registry.go +++ b/constraint/solver/hint_registry.go @@ -2,12 +2,13 @@ package solver import ( "fmt" + "log/slog" "maps" "math/big" "sync" "github.com/consensys/gnark/internal/hints" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" ) func init() { @@ -23,12 +24,12 @@ var ( func RegisterHint(hintFns ...Hint) { registryM.Lock() defer registryM.Unlock() + log := logger.Logger() for _, hintFn := range hintFns { key := GetHintID(hintFn) name := GetHintName(hintFn) if _, ok := registry[key]; ok { - log := logger.Logger() - log.Debug().Str("name", name).Msg("function registered multiple times") + logger.Trace(log, "hint registered multiple times", slog.String("name", name)) continue } registry[key] = hintFn From bad00b068b9572463e6a44ec9a0be741648e4949 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 18 May 2026 08:40:55 +0000 Subject: [PATCH 12/44] chore: use new logger for solver hint registration option --- constraint/solver/options.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/constraint/solver/options.go b/constraint/solver/options.go index 9856b4f6e5..06aee31d30 100644 --- a/constraint/solver/options.go +++ b/constraint/solver/options.go @@ -23,14 +23,15 @@ type Config struct { // WithHints is a solver option that specifies additional hint functions to be used // by the constraint solver. func WithHints(hintFunctions ...Hint) Option { - log := logger.Logger() return func(opt *Config) error { + // use logger from config -- NewConfig initializes it. + log := opt.Logger // it is an error to register hint function several times, but as the // prover already checks it then omit here. for _, h := range hintFunctions { uuid := GetHintID(h) if _, ok := opt.HintFunctions[uuid]; ok { - log.Warn().Int("hintID", int(uuid)).Str("name", GetHintName(h)).Msg("duplicate hint function") + log.Debug("WithHints called for already registered hint function, skipping", slog.Int("hintID", int(uuid)), slog.String("name", GetHintName(h))) } else { opt.HintFunctions[uuid] = h } @@ -42,6 +43,8 @@ func WithHints(hintFunctions ...Hint) Option { // OverrideHint forces the solver to use provided hint function for given id. func OverrideHint(id HintID, f Hint) Option { return func(opt *Config) error { + log := opt.Logger + log.Debug("Overriding hint function", slog.Int("hintID", int(id)), slog.String("name", GetHintName(f))) opt.HintFunctions[id] = f return nil } From 7183d13d0e88f6b9a904d530b52252f5434d2048 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 18 May 2026 08:41:39 +0000 Subject: [PATCH 13/44] chore: use new logger in solver checkSerialization --- constraint/core.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/constraint/core.go b/constraint/core.go index 9d8fc6a21b..7f35896da9 100644 --- a/constraint/core.go +++ b/constraint/core.go @@ -2,6 +2,7 @@ package constraint import ( "fmt" + "log/slog" "math/big" "strconv" "sync" @@ -11,9 +12,9 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/debug" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/smallfields" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" "github.com/consensys/gnark/profile" ) @@ -189,7 +190,7 @@ func (system *System) CheckSerializationHeader() error { if binaryVersion.Compare(objectVersion) != 0 { log := logger.Logger() - log.Warn().Str("binary", binaryVersion.String()).Str("object", objectVersion.String()).Msg("gnark version (binary) mismatch with constraint system. there are no guarantees on compatibility") + log.Warn("gnark version (binary) mismatch with constraint system. there are no guarantees on compatibility", slog.String("binary", binaryVersion.String()), slog.String("object", objectVersion.String())) } // TODO @gbotrel maintain version changes and compare versions properly From 9ff470da819d594560f65b177159909031136873 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 18 May 2026 08:43:06 +0000 Subject: [PATCH 14/44] feat: use new logger in solver --- constraint/babybear/solver.go | 18 +++++++--------- constraint/babybear/system.go | 20 +++++++++++------- constraint/bls12-377/solver.go | 18 +++++++--------- constraint/bls12-377/system.go | 20 +++++++++++------- constraint/bls12-381/solver.go | 18 +++++++--------- constraint/bls12-381/system.go | 20 +++++++++++------- constraint/bn254/solver.go | 18 +++++++--------- constraint/bn254/system.go | 20 +++++++++++------- constraint/bw6-761/solver.go | 18 +++++++--------- constraint/bw6-761/system.go | 20 +++++++++++------- constraint/grumpkin/solver.go | 18 +++++++--------- constraint/grumpkin/system.go | 20 +++++++++++------- constraint/koalabear/solver.go | 18 +++++++--------- constraint/koalabear/system.go | 20 +++++++++++------- constraint/tinyfield/solver.go | 18 +++++++--------- constraint/tinyfield/system.go | 20 +++++++++++------- .../template/representations/solver.go.tmpl | 21 +++++++------------ .../template/representations/system.go.tmpl | 17 +++++++++------ 18 files changed, 179 insertions(+), 163 deletions(-) diff --git a/constraint/babybear/solver.go b/constraint/babybear/solver.go index 2c9f877699..59af56db14 100644 --- a/constraint/babybear/solver.go +++ b/constraint/babybear/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" fr "github.com/consensys/gnark-crypto/field/babybear" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/babybear/system.go b/constraint/babybear/system.go index b1db22916b..338ba660cd 100644 --- a/constraint/babybear/system.go +++ b/constraint/babybear/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -52,15 +54,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -77,11 +83,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/constraint/bls12-377/solver.go b/constraint/bls12-377/solver.go index b217b92856..688e242792 100644 --- a/constraint/bls12-377/solver.go +++ b/constraint/bls12-377/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/bls12-377/system.go b/constraint/bls12-377/system.go index 788cf8ec87..37d82018d0 100644 --- a/constraint/bls12-377/system.go +++ b/constraint/bls12-377/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -54,15 +56,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -79,11 +85,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/constraint/bls12-381/solver.go b/constraint/bls12-381/solver.go index 94c516b572..c3173c5304 100644 --- a/constraint/bls12-381/solver.go +++ b/constraint/bls12-381/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/bls12-381/system.go b/constraint/bls12-381/system.go index 3e98fe8807..32ccafb3a9 100644 --- a/constraint/bls12-381/system.go +++ b/constraint/bls12-381/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -54,15 +56,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -79,11 +85,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/constraint/bn254/solver.go b/constraint/bn254/solver.go index 9ba4439b20..be59bd36e9 100644 --- a/constraint/bn254/solver.go +++ b/constraint/bn254/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" "github.com/consensys/gnark-crypto/ecc/bn254/fr" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/bn254/system.go b/constraint/bn254/system.go index 3580cfc94e..b75b14c4d9 100644 --- a/constraint/bn254/system.go +++ b/constraint/bn254/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -54,15 +56,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -79,11 +85,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/constraint/bw6-761/solver.go b/constraint/bw6-761/solver.go index 892a877eaf..5152df5ee3 100644 --- a/constraint/bw6-761/solver.go +++ b/constraint/bw6-761/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/bw6-761/system.go b/constraint/bw6-761/system.go index b4a079675e..eb0281957a 100644 --- a/constraint/bw6-761/system.go +++ b/constraint/bw6-761/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -54,15 +56,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -79,11 +85,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/constraint/grumpkin/solver.go b/constraint/grumpkin/solver.go index e2be5b9e7a..a54ef82131 100644 --- a/constraint/grumpkin/solver.go +++ b/constraint/grumpkin/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" "github.com/consensys/gnark-crypto/ecc/grumpkin/fr" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/grumpkin/system.go b/constraint/grumpkin/system.go index 9b7fbbd176..23c18257cf 100644 --- a/constraint/grumpkin/system.go +++ b/constraint/grumpkin/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -52,15 +54,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -77,11 +83,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/constraint/koalabear/solver.go b/constraint/koalabear/solver.go index 6c4b3099e2..1aaa9dfd49 100644 --- a/constraint/koalabear/solver.go +++ b/constraint/koalabear/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" fr "github.com/consensys/gnark-crypto/field/koalabear" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/koalabear/system.go b/constraint/koalabear/system.go index e6982999ea..1e2e4adde0 100644 --- a/constraint/koalabear/system.go +++ b/constraint/koalabear/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -52,15 +54,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -77,11 +83,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/constraint/tinyfield/solver.go b/constraint/tinyfield/solver.go index d6e0727061..647a6aa095 100644 --- a/constraint/tinyfield/solver.go +++ b/constraint/tinyfield/solver.go @@ -15,10 +15,12 @@ import ( "strings" "sync" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" fr "github.com/consensys/gnark/internal/smallfields/tinyfield" ) @@ -39,7 +41,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -71,13 +73,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -254,13 +250,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/constraint/tinyfield/system.go b/constraint/tinyfield/system.go index c0f16abe59..d087280060 100644 --- a/constraint/tinyfield/system.go +++ b/constraint/tinyfield/system.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/consensys/gnark/backend/witness" + "log/slog" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/logger" + + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -52,15 +54,19 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -77,11 +83,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor diff --git a/internal/generator/backend/template/representations/solver.go.tmpl b/internal/generator/backend/template/representations/solver.go.tmpl index 5bc5bcde03..9027f54116 100644 --- a/internal/generator/backend/template/representations/solver.go.tmpl +++ b/internal/generator/backend/template/representations/solver.go.tmpl @@ -8,10 +8,11 @@ import ( "strings" "sync" - "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/constraint" + "github.com/consensys/gnark/constraint" csolver "github.com/consensys/gnark/constraint/solver" - "github.com/rs/zerolog" + "context" + "log/slog" + "github.com/consensys/gnark-crypto/ecc" {{ template "import_fr" . }} ) @@ -31,7 +32,7 @@ type solver struct { nativeHints map[csolver.HintID]nativeHintFn // used to out api.Println - logger zerolog.Logger + logger *slog.Logger nbTasks int a, b, c fr.Vector // R1CS solver builds the a,b,c matrices @@ -63,13 +64,7 @@ var nativeHintByName = map[string]nativeHintFn{ "github.com/consensys/gnark/std/math/bits.nBits": (*solver).solveBitsNBits, } -func newSolver(cs *system, witness fr.Vector, opts ...csolver.Option) (*solver, error) { - // parse options - opt, err := csolver.NewConfig(opts...) - if err != nil { - return nil, err - } - +func newSolver(cs *system, witness fr.Vector, opt *csolver.Config) (*solver, error) { // check witness size witnessOffset := 0 if cs.Type == constraint.SystemR1CS { @@ -247,13 +242,13 @@ func (s *solver) valueWithCoeff(cID, vID uint32) fr.Element { } func (s *solver) printLogs(logs []constraint.LogEntry) { - if s.logger.GetLevel() == zerolog.Disabled { + if !s.logger.Enabled(context.Background(), slog.LevelDebug) { return } for i := 0; i < len(logs); i++ { logLine := s.logValue(logs[i]) - s.logger.Debug().Str(zerolog.CallerFieldName, logs[i].Caller).Msg(logLine) + s.logger.Debug("api.Println", slog.String(slog.SourceKey, logs[i].Caller), slog.String("debug", logLine)) } } diff --git a/internal/generator/backend/template/representations/system.go.tmpl b/internal/generator/backend/template/representations/system.go.tmpl index 74f838691d..828a2ece33 100644 --- a/internal/generator/backend/template/representations/system.go.tmpl +++ b/internal/generator/backend/template/representations/system.go.tmpl @@ -4,7 +4,8 @@ import ( csolver "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/constraint" - "github.com/consensys/gnark/logger" + "log/slog" + "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark-crypto/ecc" @@ -51,16 +52,20 @@ func newSystem(capacity int, t constraint.SystemType) *system { // If it's a R1CS returns R1CSSolution // If it's a SparseR1CS returns SparseR1CSSolution func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, error) { - log := logger.Logger().With().Int("nbConstraints", cs.GetNbConstraints()).Logger() + opt, err := csolver.NewConfig(opts...) + if err != nil { + return nil, err + } + log := opt.Logger.With(slog.Int("nbConstraints", cs.GetNbConstraints())) start := time.Now() v := witness.Vector().(fr.Vector) // init the solver - solver, err := newSolver(cs, v, opts...) + solver, err := newSolver(cs, v, &opt) if err != nil { - log.Err(err).Send() + log.Error("constraint system solver init failed", slog.Any("err", err)) return nil, err } @@ -77,11 +82,11 @@ func (cs *system) Solve(witness witness.Witness, opts ...csolver.Option) (any, e // run it. if err := solver.run(); err != nil { - log.Err(err).Send() + log.Error("constraint system solving failed", slog.Any("err", err)) return nil, err } - log.Debug().Dur("took", time.Since(start)).Msg("constraint system solver done") + log.Debug("constraint system solver done", slog.Duration("took", time.Since(start))) // format the solution // TODO @gbotrel revisit post-refactor From 4486cd72ce55547fea38a6dc5e115409966298b8 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 18 May 2026 08:44:56 +0000 Subject: [PATCH 15/44] chore: provide logger to solve in icicle --- backend/accelerated/icicle/groth16/bls12-377/icicle.go | 4 +++- backend/accelerated/icicle/groth16/bls12-381/icicle.go | 4 +++- backend/accelerated/icicle/groth16/bn254/icicle.go | 4 +++- backend/accelerated/icicle/groth16/bw6-761/icicle.go | 4 +++- .../internal/generator/templates/groth16.icicle.go.tmpl | 4 +++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/accelerated/icicle/groth16/bls12-377/icicle.go b/backend/accelerated/icicle/groth16/bls12-377/icicle.go index 631e68f302..ef71835347 100644 --- a/backend/accelerated/icicle/groth16/bls12-377/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-377/icicle.go @@ -811,7 +811,9 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic proof := &groth16_bls12377.Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) privateCommittedValuesDevice := make([]icicle_core.DeviceSlice, len(commitmentInfo)) diff --git a/backend/accelerated/icicle/groth16/bls12-381/icicle.go b/backend/accelerated/icicle/groth16/bls12-381/icicle.go index b3d2b09fa2..1d86e9955a 100644 --- a/backend/accelerated/icicle/groth16/bls12-381/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-381/icicle.go @@ -811,7 +811,9 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic proof := &groth16_bls12381.Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) privateCommittedValuesDevice := make([]icicle_core.DeviceSlice, len(commitmentInfo)) diff --git a/backend/accelerated/icicle/groth16/bn254/icicle.go b/backend/accelerated/icicle/groth16/bn254/icicle.go index 3b64fe1ab8..237d51e213 100644 --- a/backend/accelerated/icicle/groth16/bn254/icicle.go +++ b/backend/accelerated/icicle/groth16/bn254/icicle.go @@ -811,7 +811,9 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic proof := &groth16_bn254.Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) privateCommittedValuesDevice := make([]icicle_core.DeviceSlice, len(commitmentInfo)) diff --git a/backend/accelerated/icicle/groth16/bw6-761/icicle.go b/backend/accelerated/icicle/groth16/bw6-761/icicle.go index 8f49fb8638..0407949a5e 100644 --- a/backend/accelerated/icicle/groth16/bw6-761/icicle.go +++ b/backend/accelerated/icicle/groth16/bw6-761/icicle.go @@ -800,7 +800,9 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic proof := &groth16_bw6761.Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) privateCommittedValuesDevice := make([]icicle_core.DeviceSlice, len(commitmentInfo)) diff --git a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl index d10e0cd65c..f49d5cc9fe 100644 --- a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl +++ b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl @@ -824,7 +824,9 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic proof := &groth16_{{ .CurvePkg }}.Proof{Commitments: make([]curve.G1Affine, len(commitmentInfo))} - solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] + solverOpts := make([]solver.Option, 0, len(opt.SolverOpts)+2) + solverOpts = append(solverOpts, solver.WithLogger(opt.Logger)) + solverOpts = append(solverOpts, opt.SolverOpts...) privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) privateCommittedValuesDevice := make([]icicle_core.DeviceSlice, len(commitmentInfo)) From fc54dadd2dd298e4c2e2d83ce5ea2bcdf6ebf981 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 18 May 2026 08:45:53 +0000 Subject: [PATCH 16/44] feat: add DisabledLogger option --- internal/logger/logger.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 029eb45c2b..b0b2a6f7d2 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -36,7 +36,7 @@ func Logger() *slog.Logger { defaultOnce.Do(func() { level := levelFromEnv(debug.Debug) if level == LevelDisabled { - defaultLogger = slog.New(newHandler(io.Discard, level)) + defaultLogger = DisabledLogger() return } defaultLogger = slog.New(newHandler(defaultOutput, level)) @@ -45,6 +45,11 @@ func Logger() *slog.Logger { return defaultLogger } +// DisabledLogger returns a logger that discards all records. +func DisabledLogger() *slog.Logger { + return slog.New(newHandler(io.Discard, LevelDisabled)) +} + func Trace(log *slog.Logger, msg string, attrs ...slog.Attr) { log.LogAttrs(context.Background(), LevelTrace, msg, attrs...) } From d8159c7866836d38dce02556a387a8894e25c79f Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 22:38:46 +0000 Subject: [PATCH 17/44] feat: provide Logger() method in Compiler --- frontend/builder.go | 4 ++++ frontend/compile.go | 47 +++++++++++++++++++++++++++++-------- frontend/cs/commitment.go | 4 ++-- frontend/cs/r1cs/builder.go | 13 +++++----- frontend/cs/scs/builder.go | 13 +++++----- frontend/schema/schema.go | 5 ++-- frontend/schema/walk.go | 5 ++-- 7 files changed, 63 insertions(+), 28 deletions(-) diff --git a/frontend/builder.go b/frontend/builder.go index b8c1506712..1aed989a3b 100644 --- a/frontend/builder.go +++ b/frontend/builder.go @@ -1,6 +1,7 @@ package frontend import ( + "log/slog" "math/big" "github.com/consensys/gnark/constraint" @@ -69,6 +70,9 @@ type Compiler interface { // FieldBitLen returns the number of bits needed to represent an element in the scalar field FieldBitLen() int + // Logger returns the compiler logger. + Logger() *slog.Logger + // Defer is called after circuit.Define() and before Compile(). This method // allows for the circuits to register callbacks which finalize batching // operations etc. Unlike Go defer, it is not locally scoped. diff --git a/frontend/compile.go b/frontend/compile.go index 55990c928f..f91ff3aac6 100644 --- a/frontend/compile.go +++ b/frontend/compile.go @@ -3,17 +3,19 @@ package frontend import ( "errors" "fmt" + "log/slog" "math/big" "reflect" "strings" + "time" "github.com/consensys/gnark" "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/debug" "github.com/consensys/gnark/frontend/schema" "github.com/consensys/gnark/internal/circuitdefer" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/smallfields" - "github.com/consensys/gnark/logger" ) // Compile will generate a ConstraintSystem from the given circuit @@ -67,34 +69,45 @@ func CompileU32(field *big.Int, newBuilder NewBuilderU32, circuit Circuit, opts // [CompileU32] are more convenient as are explicitly constrained to specific // types. func CompileGeneric[E constraint.Element](field *big.Int, newBuilder NewBuilderGeneric[E], circuit Circuit, opts ...CompileOption) (constraint.ConstraintSystemGeneric[E], error) { - log := logger.Logger() - log.Info().Msg("compiling circuit") // parse options opt := defaultCompileConfig() for _, o := range opts { if err := o(&opt); err != nil { - log.Err(err).Msg("applying compile option") + opt.Logger.Error("applying compile option", slog.Any("err", err)) return nil, fmt.Errorf("apply option: %w", err) } } + log := opt.Logger + logger.Trace(log, "compiling circuit") // instantiate new builder builder, err := newBuilder(field, opt) if err != nil { - log.Err(err).Msg("instantiating builder") + log.Error("instantiating builder", slog.Any("err", err)) return nil, fmt.Errorf("new compiler: %w", err) } + start := time.Now() // parse the circuit builds a schema of the circuit // and call circuit.Define() method to initialize a list of constraints in the compiler if err = parseCircuit(builder, circuit); err != nil { - log.Err(err).Msg("parsing circuit") + log.Error("parsing circuit", slog.Any("err", err)) return nil, fmt.Errorf("parse circuit: %w", err) - } // compile the circuit into its final form - return builder.Compile() + ccs, err := builder.Compile() + if err != nil { + log.Error("compiling circuit", slog.Any("err", err)) + return nil, fmt.Errorf("compile circuit: %w", err) + } + + log.Debug("circuit compiled", + slog.Duration("took", time.Since(start)), + slog.Int("nbConstraints", ccs.GetNbConstraints()), + slog.Int("nbPublic", ccs.GetNbPublicVariables()), + slog.Int("nbSecret", ccs.GetNbSecretVariables())) + return ccs, nil } func parseCircuit[E constraint.Element](builder Builder[E], circuit Circuit) (err error) { @@ -108,8 +121,8 @@ func parseCircuit[E constraint.Element](builder Builder[E], circuit Circuit) (er return err } - log := logger.Logger() - log.Info().Int("nbSecret", s.Secret).Int("nbPublic", s.Public).Msg("parsed circuit inputs") + log := builder.Compiler().Logger() + logger.Trace(log, "parsed circuit inputs", slog.Int("nbSecret", s.Secret), slog.Int("nbPublic", s.Public)) // leaf handlers are called when encountering leafs in the circuit data struct // leafs are Constraints that need to be initialized in the context of compiling a circuit @@ -187,6 +200,7 @@ type CompileOption func(opt *CompileConfig) error func defaultCompileConfig() CompileConfig { return CompileConfig{ CompressThreshold: 300, + Logger: logger.Logger(), } } @@ -194,6 +208,7 @@ type CompileConfig struct { Capacity int IgnoreUnconstrainedInputs bool CompressThreshold int + Logger *slog.Logger } // WithCapacity is a compile option that specifies the estimated capacity needed @@ -243,6 +258,18 @@ func WithCompressThreshold(threshold int) CompileOption { } } +// WithLogger sets the logger used during circuit compilation. If this option is +// not provided, then the default logger is used. Passing nil disables logging. +func WithLogger(log *slog.Logger) CompileOption { + return func(opt *CompileConfig) error { + if log == nil { + log = logger.DisabledLogger() + } + opt.Logger = log + return nil + } +} + var tVariable reflect.Type func init() { diff --git a/frontend/cs/commitment.go b/frontend/cs/commitment.go index 6ff81a239a..264a85c92e 100644 --- a/frontend/cs/commitment.go +++ b/frontend/cs/commitment.go @@ -8,14 +8,14 @@ import ( "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/debug" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" ) func Bsb22CommitmentComputePlaceholder(mod *big.Int, _ []*big.Int, output []*big.Int) (err error) { if testing.Testing() || debug.Debug { // usually we only run solver without prover during testing log := logger.Logger() - log.Error().Msg("Augmented commitment hint not replaced. Proof will not be sound and verification will fail!") + log.Warn("Augmented commitment hint not replaced. Proof will not be sound and verification will fail!") output[0], err = rand.Int(rand.Reader, mod) if output[0].Sign() == 0 { // a commit == 0 is unlikely; happens quite often in tests diff --git a/frontend/cs/r1cs/builder.go b/frontend/cs/r1cs/builder.go index 85bf3e3f75..4d87daa5e2 100644 --- a/frontend/cs/r1cs/builder.go +++ b/frontend/cs/r1cs/builder.go @@ -5,6 +5,7 @@ package r1cs import ( "errors" + "log/slog" "math/big" "reflect" "sort" @@ -22,7 +23,6 @@ import ( "github.com/consensys/gnark/internal/kvstore" "github.com/consensys/gnark/internal/smallfields/tinyfield" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" babybearr1cs "github.com/consensys/gnark/constraint/babybear" bls12377r1cs "github.com/consensys/gnark/constraint/bls12-377" @@ -139,6 +139,10 @@ func newBuilder[E constraint.Element](field *big.Int, config frontend.CompileCon return bldr } +func (builder *builder[E]) Logger() *slog.Logger { + return builder.config.Logger +} + // newInternalVariable creates a new wire, appends it on the list of wires of the circuit, sets // the wire's id to the number of wires, and returns it func (builder *builder[E]) newInternalVariable() expr.LinearExpression[E] { @@ -275,14 +279,11 @@ func init() { // Compile constructs a rank-1 constraint system func (builder *builder[E]) Compile() (constraint.ConstraintSystemGeneric[E], error) { // TODO if already compiled, return builder.cs object - log := logger.Logger() - log.Info(). - Int("nbConstraints", builder.cs.GetNbConstraints()). - Msg("building constraint builder") + log := builder.Logger() // ensure all inputs and hints are constrained if err := builder.cs.CheckUnconstrainedWires(); err != nil { - log.Warn().Msg("circuit has unconstrained inputs") + log.Warn("circuit has unconstrained inputs") if !builder.config.IgnoreUnconstrainedInputs { return nil, err } diff --git a/frontend/cs/scs/builder.go b/frontend/cs/scs/builder.go index f39d9e614a..a12f15858e 100644 --- a/frontend/cs/scs/builder.go +++ b/frontend/cs/scs/builder.go @@ -5,6 +5,7 @@ package scs import ( "fmt" + "log/slog" "math/big" "reflect" "sort" @@ -21,7 +22,6 @@ import ( "github.com/consensys/gnark/internal/kvstore" "github.com/consensys/gnark/internal/smallfields/tinyfield" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" babybearr1cs "github.com/consensys/gnark/constraint/babybear" bls12377r1cs "github.com/consensys/gnark/constraint/bls12-377" @@ -135,6 +135,10 @@ func newBuilder[E constraint.Element](field *big.Int, config frontend.CompileCon return b } +func (builder *builder[E]) Logger() *slog.Logger { + return builder.config.Logger +} + func (builder *builder[E]) Field() *big.Int { return builder.cs.Field() } @@ -288,15 +292,12 @@ func init() { } func (builder *builder[E]) Compile() (constraint.ConstraintSystemGeneric[E], error) { - log := logger.Logger() - log.Info(). - Int("nbConstraints", builder.cs.GetNbConstraints()). - Msg("building constraint builder") + log := builder.Logger() // ensure all inputs and hints are constrained err := builder.cs.CheckUnconstrainedWires() if err != nil { - log.Warn().Msg("circuit has unconstrained inputs") + log.Warn("circuit has unconstrained inputs") if !builder.config.IgnoreUnconstrainedInputs { return nil, err } diff --git a/frontend/schema/schema.go b/frontend/schema/schema.go index 698224de90..46518385e7 100644 --- a/frontend/schema/schema.go +++ b/frontend/schema/schema.go @@ -6,12 +6,13 @@ package schema import ( "fmt" "io" + "log/slog" "math/big" "reflect" "strconv" "strings" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" ) // Schema represents the structure of a gnark circuit (/ witness) @@ -314,7 +315,7 @@ func parse(r []Field, input interface{}, target reflect.Type, parentFullName, pa if tValue.Len() == 0 { if reflect.SliceOf(target) == tValue.Type() { log := logger.Logger() - log.Warn().Str("slice name", parentGoName).Str("slice type", reflect.SliceOf(target).String()).Msg("ignoring uninitialized slice") + log.Warn("ignoring uninitialized slice", slog.String("slice name", parentGoName), slog.String("slice type", reflect.SliceOf(target).String())) } return r, nil } diff --git a/frontend/schema/walk.go b/frontend/schema/walk.go index dc9cbc2f47..1e5597aff8 100644 --- a/frontend/schema/walk.go +++ b/frontend/schema/walk.go @@ -2,13 +2,14 @@ package schema import ( "fmt" + "log/slog" "math/big" "reflect" "strconv" "strings" "github.com/consensys/gnark/frontend/schema/internal/reflectwalk" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" ) // Walk walks through the provided object and stops when it encounters objects of type tLeaf @@ -90,7 +91,7 @@ func (w *walker) Slice(value reflect.Value) error { if value.Type() == w.targetSlice { if value.Len() == 0 { log := logger.Logger() - log.Warn().Str("slice name", w.name()).Str("slice type", reflect.SliceOf(w.target).String()).Msg("ignoring uninitialized slice") + log.Warn("ignoring uninitialized slice", slog.String("slice name", w.name()), slog.String("slice type", reflect.SliceOf(w.target).String())) return nil } return w.handleLeaves(value) From e0993f5ebbe3f56ac173b481bb4e03aaead4469b Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 22:39:12 +0000 Subject: [PATCH 18/44] chore: reduce override hint log level to trace (BSB hint) --- constraint/solver/options.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/constraint/solver/options.go b/constraint/solver/options.go index 06aee31d30..6d820c76a3 100644 --- a/constraint/solver/options.go +++ b/constraint/solver/options.go @@ -43,8 +43,7 @@ func WithHints(hintFunctions ...Hint) Option { // OverrideHint forces the solver to use provided hint function for given id. func OverrideHint(id HintID, f Hint) Option { return func(opt *Config) error { - log := opt.Logger - log.Debug("Overriding hint function", slog.Int("hintID", int(id)), slog.String("name", GetHintName(f))) + logger.Trace(opt.Logger, "Overriding hint function", slog.Int("hintID", int(id)), slog.String("name", GetHintName(f))) opt.HintFunctions[id] = f return nil } From f13121572c7663c0185c11030c0523c5c222a620 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 22:42:25 +0000 Subject: [PATCH 19/44] feat: use compiler logger in widecommitter --- internal/widecommitter/widecommitter.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal/widecommitter/widecommitter.go b/internal/widecommitter/widecommitter.go index 3f6d67532b..6d29efd547 100644 --- a/internal/widecommitter/widecommitter.go +++ b/internal/widecommitter/widecommitter.go @@ -8,7 +8,6 @@ import ( "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/logger" "golang.org/x/crypto/sha3" ) @@ -31,8 +30,8 @@ func From(newBuilder frontend.NewBuilderU32) frontend.NewBuilderU32 { if err != nil { return nil, err } - log := logger.Logger() - log.Warn().Msg("using fake wide committer, no checks will be performed. Use only for testing") + log := b.Compiler().Logger() + log.Warn("using fake wide committer, no checks will be performed. Use only for testing") return &wrappedBuilder{b}, nil } } From 527d6de12d2f707c97d81c393fca9027547d5abc Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 22:45:59 +0000 Subject: [PATCH 20/44] feat: use compiler logger in std --- internal/compilelogger/compilelogger.go | 10 +++--- internal/compilelogger/compilelogger_test.go | 38 +++++++++++--------- std/algebra/emulated/sw_bls12381/g2.go | 4 +-- std/algebra/native/sw_bls12377/g1.go | 4 +-- std/algebra/native/sw_grumpkin/g1.go | 4 +-- std/math/emulated/field.go | 17 ++++----- std/rangecheck/rangecheck_commit.go | 5 ++- 7 files changed, 44 insertions(+), 38 deletions(-) diff --git a/internal/compilelogger/compilelogger.go b/internal/compilelogger/compilelogger.go index c554b5813f..46ee6eccfb 100644 --- a/internal/compilelogger/compilelogger.go +++ b/internal/compilelogger/compilelogger.go @@ -4,10 +4,11 @@ package compilelogger import ( + "context" + "log/slog" + "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/internal/kvstore" - "github.com/consensys/gnark/logger" - "github.com/rs/zerolog" ) type compileLoggerKey struct { @@ -25,7 +26,7 @@ type compileLoggerKey struct { // // LogOnce panics if the api does not implement [kvstore.Store], which should // never happen since the compiler is expected to implement it. -func LogOnce(api frontend.Compiler, level zerolog.Level, identifier, msg string, args ...any) { +func LogOnce(api frontend.Compiler, level slog.Level, identifier, msg string, args ...any) { kv, ok := api.(kvstore.Store) if !ok { panic("compiler should implement key-value store") @@ -37,6 +38,5 @@ func LogOnce(api frontend.Compiler, level zerolog.Level, identifier, msg string, // set the key to avoid logging again with the same identifier kv.SetKeyValue(key, struct{}{}) - l := logger.Logger() - l.WithLevel(level).Msgf(msg, args...) + api.Logger().Log(context.Background(), level, msg, args...) } diff --git a/internal/compilelogger/compilelogger_test.go b/internal/compilelogger/compilelogger_test.go index 969d477338..36fae4943a 100644 --- a/internal/compilelogger/compilelogger_test.go +++ b/internal/compilelogger/compilelogger_test.go @@ -3,6 +3,7 @@ package compilelogger_test import ( "bytes" "fmt" + "log/slog" "os" "strings" "testing" @@ -10,8 +11,6 @@ import ( "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/internal/compilelogger" - "github.com/consensys/gnark/logger" - "github.com/rs/zerolog" "github.com/consensys/gnark-crypto/ecc" ) @@ -26,9 +25,9 @@ func (c *testCircuit) Define(api frontend.API) error { if !ok { panic("api is not a compiler") } - compilelogger.LogOnce(compiler, zerolog.WarnLevel, "dup", "duplicate message") - compilelogger.LogOnce(compiler, zerolog.WarnLevel, "dup", "duplicate message") - compilelogger.LogOnce(compiler, zerolog.WarnLevel, "unique", "unique message") + compilelogger.LogOnce(compiler, slog.LevelWarn, "dup", "duplicate message") + compilelogger.LogOnce(compiler, slog.LevelWarn, "dup", "duplicate message") + compilelogger.LogOnce(compiler, slog.LevelWarn, "unique", "unique message") api.AssertIsEqual(c.X, c.X) return nil } @@ -38,33 +37,40 @@ type exampleCircuit struct{ X frontend.Variable } func (c *exampleCircuit) Define(api frontend.API) error { compiler := api.(frontend.Compiler) - compilelogger.LogOnce(compiler, zerolog.WarnLevel, "key-a", "warning A") - compilelogger.LogOnce(compiler, zerolog.WarnLevel, "key-a", "warning A") // suppressed: same key - compilelogger.LogOnce(compiler, zerolog.WarnLevel, "key-b", "warning B") + compilelogger.LogOnce(compiler, slog.LevelWarn, "key-a", "warning A") + compilelogger.LogOnce(compiler, slog.LevelWarn, "key-a", "warning A") // suppressed: same key + compilelogger.LogOnce(compiler, slog.LevelWarn, "key-b", "warning B") api.AssertIsEqual(c.X, c.X) return nil } func ExampleLogOnce() { // WarnLevel filters the framework's own info logs so only our messages appear. - logger.Set(zerolog.New(os.Stdout).Level(zerolog.WarnLevel)) - defer logger.Disable() + log := slog.New(slog.NewJSONHandler( + os.Stdout, + &slog.HandlerOptions{ + Level: slog.LevelWarn, + ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { + if a.Key == slog.TimeKey && a.Value.Kind() == slog.KindTime { + return slog.Attr{} + } + return a + }})) - _, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &exampleCircuit{}) + _, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &exampleCircuit{}, frontend.WithLogger(log)) if err != nil { fmt.Println("compile error:", err) } // Output: - // {"level":"warn","message":"warning A"} - // {"level":"warn","message":"warning B"} + // {"level":"WARN","msg":"warning A"} + // {"level":"WARN","msg":"warning B"} } func TestLogOnce(t *testing.T) { var buf bytes.Buffer - logger.Set(zerolog.New(&buf).Level(zerolog.WarnLevel)) - defer logger.Disable() + log := slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelWarn})) - _, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &testCircuit{}) + _, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &testCircuit{}, frontend.WithLogger(log)) if err != nil { t.Fatal(err) } diff --git a/std/algebra/emulated/sw_bls12381/g2.go b/std/algebra/emulated/sw_bls12381/g2.go index 1b75c41bbd..7853566ce1 100644 --- a/std/algebra/emulated/sw_bls12381/g2.go +++ b/std/algebra/emulated/sw_bls12381/g2.go @@ -2,6 +2,7 @@ package sw_bls12381 import ( "fmt" + "log/slog" "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" @@ -11,7 +12,6 @@ import ( "github.com/consensys/gnark/std/algebra/algopts" "github.com/consensys/gnark/std/algebra/emulated/fields_bls12381" "github.com/consensys/gnark/std/math/emulated" - "github.com/rs/zerolog" ) type G2 struct { @@ -637,7 +637,7 @@ func (g2 *G2) scalarMulGLV(Q *G2Affine, s *Scalar, opts ...algopts.AlgebraOption panic(err) } if cfg.IncompleteArithmetic { - compilelogger.LogOnce(g2.api.Compiler(), zerolog.InfoLevel, + compilelogger.LogOnce(g2.api.Compiler(), slog.LevelInfo, "sw_bls12_381/scalarMulGLV", "WithIncompleteArithmetic is deprecated in (*sw_bls12381.G2).scalarMulGLV and complete arithmetic is always used") } // if Q=(0,0) we assign a dummy (1,1) to Q and continue diff --git a/std/algebra/native/sw_bls12377/g1.go b/std/algebra/native/sw_bls12377/g1.go index 5c4722091f..a8d7498964 100644 --- a/std/algebra/native/sw_bls12377/g1.go +++ b/std/algebra/native/sw_bls12377/g1.go @@ -5,11 +5,11 @@ package sw_bls12377 import ( "fmt" + "log/slog" "math/big" bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" - "github.com/rs/zerolog" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/internal/compilelogger" @@ -215,7 +215,7 @@ func (p *G1Affine) scalarMulGLV(api frontend.API, Q G1Affine, s frontend.Variabl panic(err) } if cfg.IncompleteArithmetic { - compilelogger.LogOnce(api.Compiler(), zerolog.InfoLevel, + compilelogger.LogOnce(api.Compiler(), slog.LevelInfo, "sw_bls12377/g1/scalarMulGLV", "WithIncompleteArithmetic is deprecated for (*sw_bls12377.G1Affine).scalarMulGLV and complete arithmetic is always used") } diff --git a/std/algebra/native/sw_grumpkin/g1.go b/std/algebra/native/sw_grumpkin/g1.go index 22feb69c53..27c986666d 100644 --- a/std/algebra/native/sw_grumpkin/g1.go +++ b/std/algebra/native/sw_grumpkin/g1.go @@ -5,6 +5,7 @@ package sw_grumpkin import ( "fmt" + "log/slog" "math/big" fr_bn "github.com/consensys/gnark-crypto/ecc/bn254/fr" @@ -12,7 +13,6 @@ import ( "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/internal/compilelogger" "github.com/consensys/gnark/std/algebra/algopts" - "github.com/rs/zerolog" ) // G1Affine point in affine coords @@ -173,7 +173,7 @@ func (p *G1Affine) scalarMulGLV(api frontend.API, q G1Affine, s frontend.Variabl panic(err) } if cfg.IncompleteArithmetic { - compilelogger.LogOnce(api.Compiler(), zerolog.InfoLevel, + compilelogger.LogOnce(api.Compiler(), slog.LevelInfo, "sw_grumpkin/g1/scalarMulGLV", "WithIncompleteArithmetic is deprecated for (*sw_grumpkin.G1Affine).scalarMulGLV and complete arithmetic is always used") } diff --git a/std/math/emulated/field.go b/std/math/emulated/field.go index 9f308df1e5..37c5d1babb 100644 --- a/std/math/emulated/field.go +++ b/std/math/emulated/field.go @@ -4,19 +4,19 @@ import ( "cmp" "errors" "fmt" + "log/slog" "math/big" "sync" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/internal/compilelogger" "github.com/consensys/gnark/internal/kvstore" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/smallfields" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" "github.com/consensys/gnark/std/internal/fieldextension" limbs "github.com/consensys/gnark/std/internal/limbcomposition" "github.com/consensys/gnark/std/rangecheck" - "github.com/rs/zerolog" ) const ( @@ -57,7 +57,7 @@ type Field[T FieldParams] struct { oneConstOnce sync.Once oneConst *Element[T] - log zerolog.Logger + log *slog.Logger // constrainedLimbs keeps track of already range checked limbs. The map // value indicates the range check width. @@ -91,13 +91,13 @@ func NewField[T FieldParams](native frontend.API) (*Field[T], error) { } f := &Field[T]{ api: native, - log: logger.Logger(), + log: native.Compiler().Logger(), constrainedLimbs: make(map[[16]byte]int), checker: rangecheck.New(native), fParams: newStaticFieldParams[T](native.Compiler().Field()), } if smallfields.IsSmallField(native.Compiler().Field()) { - compilelogger.LogOnce(native.Compiler(), zerolog.DebugLevel, + compilelogger.LogOnce(native.Compiler(), logger.LevelTrace, "emulated/isSmallField", "using small native field, multiplication checks will be performed in extension field") extapi, err := fieldextension.NewExtension(native) @@ -309,7 +309,7 @@ func (f *Field[T]) constantValue(v *Element[T]) (*big.Int, bool) { res := new(big.Int) if err := limbs.Recompose(constLimbs, f.fParams.BitsPerLimb(), res); err != nil { - f.log.Error().Err(err).Msg("recomposing constant") + f.log.Error("recomposing constant", slog.Any("err", err)) return nil, false } return res, true @@ -388,9 +388,10 @@ func (f *Field[T]) useSmallFieldOptimization() bool { f.smallFieldMode = 2*modBits+batchingMargin < nativeBits-2 if f.smallFieldMode { - compilelogger.LogOnce(f.api.Compiler(), zerolog.DebugLevel, + compilelogger.LogOnce(f.api.Compiler(), logger.LevelTrace, "emulated/useSmallFieldOptimization", - "using small field optimization for emulated multiplication (modBits = %d, nativeBits = %d)", modBits, nativeBits) + "using small field optimization for emulated multiplication", + slog.Int("modBits", int(modBits)), slog.Int("nativeBits", int(nativeBits))) } }) return f.smallFieldMode diff --git a/std/rangecheck/rangecheck_commit.go b/std/rangecheck/rangecheck_commit.go index 0bd6ce8f26..90b11cd68c 100644 --- a/std/rangecheck/rangecheck_commit.go +++ b/std/rangecheck/rangecheck_commit.go @@ -2,6 +2,7 @@ package rangecheck import ( "fmt" + "log/slog" "math" "math/big" @@ -9,7 +10,6 @@ import ( "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/internal/frontendtype" "github.com/consensys/gnark/internal/kvstore" - "github.com/consensys/gnark/logger" "github.com/consensys/gnark/profile" "github.com/consensys/gnark/std/internal/logderivarg" ) @@ -47,9 +47,8 @@ func newCommitRangechecker(api frontend.API, opts ...Option) *commitChecker { if ch != nil { if cht, ok := ch.(*commitChecker); ok { if cfg.baseLength > 0 && cht.cfg.baseLength != cfg.baseLength { - log := logger.Logger() if cht.cfg.baseLength > 0 { - log.Warn().Msgf("rangechecker: existing checker has base length %d, requested %d. overwriting", cht.cfg.baseLength, cfg.baseLength) + api.Compiler().Logger().Warn("rangechecker: existing checker has base length %d, requested %d. overwriting", slog.Int("existingBaseLength", cht.cfg.baseLength), slog.Int("requestedBaseLength", cfg.baseLength)) } cht.cfg.baseLength = cfg.baseLength } From 6f8fa99278b05df611438ad403277d7a6719839c Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 22:50:27 +0000 Subject: [PATCH 21/44] feat: use new logger in profile --- profile/profile.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/profile/profile.go b/profile/profile.go index a03732f04e..96ce395246 100644 --- a/profile/profile.go +++ b/profile/profile.go @@ -7,6 +7,7 @@ package profile import ( "bytes" "fmt" + "log/slog" "os" "path/filepath" "runtime" @@ -14,7 +15,7 @@ import ( "sync" "sync/atomic" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/profile/internal/report" "github.com/google/pprof/profile" ) @@ -150,9 +151,9 @@ func Start(options ...Option) *Profile { log := logger.Logger() if p.filePath == "" { - log.Warn().Msg("gnark profiling enabled [not writing to disk]") + log.Warn("gnark profiling enabled [not writing to disk]") } else { - log.Info().Str("path", p.filePath).Msg("gnark profiling enabled") + log.Info("gnark profiling enabled", slog.String("path", p.filePath)) } // add the session to active sessions @@ -167,7 +168,8 @@ func (p *Profile) Stop() { log := logger.Logger() if p.chDone == nil { - log.Fatal().Msg("gnark profile stopped multiple times") + log.Error("gnark profile stopped multiple times") + os.Exit(1) } // ask worker routine to remove ourselves from the active sessions @@ -184,15 +186,16 @@ func (p *Profile) Stop() { if p.filePath != "" { f, err := os.Create(p.filePath) if err != nil { - log.Fatal().Err(err).Msg("could not create gnark profile") + log.Error("could not create gnark profile", slog.Any("err", err)) + os.Exit(1) } if err := p.pprof.Write(f); err != nil { - log.Error().Err(err).Msg("writing profile") + log.Error("writing profile", slog.Any("err", err)) } f.Close() - log.Info().Str("path", p.filePath).Msg("gnark profiling disabled") + log.Info("gnark profiling disabled", slog.String("path", p.filePath)) } else { - log.Warn().Msg("gnark profiling disabled [not writing to disk]") + log.Warn("gnark profiling disabled [not writing to disk]") } } From 5df6cca1ffdcb5fc6cac964d49b84cb0c358c2fb Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 22:51:50 +0000 Subject: [PATCH 22/44] chore: only retrieve logger when needed --- constraint/solver/hint_registry.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/constraint/solver/hint_registry.go b/constraint/solver/hint_registry.go index 02a34cb182..5304f34ff1 100644 --- a/constraint/solver/hint_registry.go +++ b/constraint/solver/hint_registry.go @@ -24,12 +24,11 @@ var ( func RegisterHint(hintFns ...Hint) { registryM.Lock() defer registryM.Unlock() - log := logger.Logger() for _, hintFn := range hintFns { key := GetHintID(hintFn) name := GetHintName(hintFn) if _, ok := registry[key]; ok { - logger.Trace(log, "hint registered multiple times", slog.String("name", name)) + logger.Trace(logger.Logger(), "hint registered multiple times", slog.String("name", name)) continue } registry[key] = hintFn From 010895c41fb421b62ba0095799d7bae23e64b416 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:15:41 +0000 Subject: [PATCH 23/44] feat: support custom logger in test engine --- test/engine.go | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/test/engine.go b/test/engine.go index c3ebba3a76..d0d03ca5a2 100644 --- a/test/engine.go +++ b/test/engine.go @@ -5,6 +5,7 @@ package test import ( "fmt" + "log/slog" "math/big" "path/filepath" "reflect" @@ -12,13 +13,14 @@ import ( "strconv" "strings" "sync/atomic" + "time" "github.com/bits-and-blooms/bitset" "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/debug" "github.com/consensys/gnark/frontend/schema" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" "golang.org/x/crypto/sha3" "github.com/consensys/gnark-crypto/ecc" @@ -46,6 +48,7 @@ type engine struct { internalVariables []*big.Int noSmallFieldCompatibility bool hintMapping map[solver.HintID]solver.Hint + logger *slog.Logger } // TestEngineOption defines an option for the test engine. @@ -90,6 +93,18 @@ func WithReplacementHint(id solver.HintID, f solver.Hint) TestEngineOption { } } +// WithEngineLogger sets the logger used by the test engine. If this option is +// not provided, then the default logger is used. Passing nil disables logging. +func WithEngineLogger(log *slog.Logger) TestEngineOption { + return func(e *engine) error { + if log == nil { + log = logger.DisabledLogger() + } + e.logger = log + return nil + } +} + // IsSolved returns an error if the test execution engine failed to execute the given circuit // with provided witness as input. // @@ -102,6 +117,7 @@ func IsSolved(circuit, witness frontend.Circuit, field *big.Int, opts ...TestEng q: new(big.Int).Set(field), constVars: false, Store: kvstore.New(), + logger: logger.Logger(), } for _, opt := range opts { if err := opt(e); err != nil { @@ -109,8 +125,6 @@ func IsSolved(circuit, witness frontend.Circuit, field *big.Int, opts ...TestEng } } - // TODO handle opt.LoggerOut ? - // we clone the circuit, in case the circuit has some attributes it uses in its Define function // set by the user. // then, we set all the variables values to the ones from the witness @@ -127,30 +141,34 @@ func IsSolved(circuit, witness frontend.Circuit, field *big.Int, opts ...TestEng } }() - log := logger.Logger() - log.Debug().Msg("running circuit in test engine") + logger.Trace(e.logger, "running circuit in test engine") cptAdd, cptMul, cptSub, cptToBinary, cptFromBinary, cptAssertIsEqual = 0, 0, 0, 0, 0, 0 var apiEngine frontend.API if smallfields.IsSmallField(e.modulus()) && !e.noSmallFieldCompatibility { + logger.Trace(e.logger, "using small field compatibility mode for test engine") apiEngine = &smallfieldEngine{engine: e} } else { apiEngine = e } + start := time.Now() if err = c.Define(apiEngine); err != nil { return fmt.Errorf("define: %w", err) } if err = callDeferred(apiEngine); err != nil { return fmt.Errorf("deferred: %w", err) } + e.logger.Debug("circuit executed in test engine", slog.Duration("took", time.Since(start))) - log.Debug().Uint64("add", cptAdd). - Uint64("sub", cptSub). - Uint64("mul", cptMul). - Uint64("equals", cptAssertIsEqual). - Uint64("toBinary", cptToBinary). - Uint64("fromBinary", cptFromBinary).Msg("counters") + logger.Trace(e.logger, "counters", + slog.Uint64("add", cptAdd), + slog.Uint64("sub", cptSub), + slog.Uint64("mul", cptMul), + slog.Uint64("equals", cptAssertIsEqual), + slog.Uint64("toBinary", cptToBinary), + slog.Uint64("fromBinary", cptFromBinary), + ) return } @@ -694,6 +712,10 @@ func (e *engine) Compiler() frontend.Compiler { return e } +func (e *engine) Logger() *slog.Logger { + return e.logger +} + func (e *engine) Commit(v ...frontend.Variable) (frontend.Variable, error) { if smallfields.IsSmallField(e.modulus()) { panic("commitment not supported for small fields") From a601cb76881394f6de5dcb17259dc5f650e57479 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:16:37 +0000 Subject: [PATCH 24/44] feat: use new logger in unsafekzg --- test/unsafekzg/kzgsrs.go | 21 +++++++++++---------- test/unsafekzg/options.go | 5 +++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/test/unsafekzg/kzgsrs.go b/test/unsafekzg/kzgsrs.go index 39abb8e734..2746051265 100644 --- a/test/unsafekzg/kzgsrs.go +++ b/test/unsafekzg/kzgsrs.go @@ -8,6 +8,7 @@ import ( "bufio" "crypto/rand" "fmt" + "log/slog" "math/big" "os" "path/filepath" @@ -17,8 +18,8 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/kzg" "github.com/consensys/gnark/constraint" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" - "github.com/consensys/gnark/logger" kzg_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/kzg" kzg_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/kzg" @@ -59,7 +60,7 @@ func NewSRS(ccs constraint.ConstraintSystem, opts ...Option) (canonical kzg.SRS, curveID := utils.FieldToCurve(ccs.Field()) - log := logger.Logger().With().Str("package", "kzgsrs").Int("size", int(sizeCanonical)).Str("curve", curveID.String()).Logger() + log := logger.Logger().With(slog.String("package", "kzgsrs"), slog.Int("size", int(sizeCanonical)), slog.String("curve", curveID.String())) cfg, err := options(opts...) if err != nil { @@ -67,34 +68,34 @@ func NewSRS(ccs constraint.ConstraintSystem, opts ...Option) (canonical kzg.SRS, } key := cacheKey(curveID, sizeCanonical, cfg.toxicValue) - log.Debug().Str("key", key).Msg("fetching SRS from mem cache") + logger.Trace(log, "fetching SRS from mem cache", slog.String("key", key)) memLock.RLock() entry, ok := cache[key] memLock.RUnlock() if ok { - log.Debug().Msg("SRS found in mem cache") + logger.Trace(log, "SRS found in mem cache") return entry.canonical, entry.lagrange, nil } - log.Debug().Msg("SRS not found in mem cache") + logger.Trace(log, "SRS not found in mem cache") if cfg.fsCache { - log.Debug().Str("key", key).Str("cacheDir", cfg.cacheDir).Msg("fetching SRS from fs cache") + logger.Trace(log, "fetching SRS from fs cache", slog.String("key", key), slog.String("cacheDir", cfg.cacheDir)) fsLock.RLock() entry, err = fsRead(key, cfg.cacheDir) fsLock.RUnlock() if err == nil { - log.Debug().Str("key", key).Msg("SRS found in fs cache") + logger.Trace(log, "SRS found in fs cache", slog.String("key", key)) canonical, lagrange = entry.canonical, entry.lagrange memLock.Lock() cache[key] = cacheEntry{canonical, lagrange} memLock.Unlock() return } else { - log.Debug().Str("key", key).Err(err).Msg("SRS not found in fs cache") + logger.Trace(log, "SRS not found in fs cache", slog.String("key", key), slog.Any("err", err)) } } - log.Debug().Msg("SRS not found in cache, generating") + logger.Trace(log, "SRS not found in cache, generating") // not in cache, generate canonical, lagrange, err = newSRS(curveID, sizeCanonical, cfg.toxicValue) @@ -109,7 +110,7 @@ func NewSRS(ccs constraint.ConstraintSystem, opts ...Option) (canonical kzg.SRS, memLock.Unlock() if cfg.fsCache && cfg.toxicValue == nil { - log.Debug().Str("key", key).Str("cacheDir", cfg.cacheDir).Msg("writing SRS to fs cache") + logger.Trace(log, "writing SRS to fs cache", slog.String("key", key), slog.String("cacheDir", cfg.cacheDir)) fsLock.Lock() fsWrite(key, cfg.cacheDir, canonical, lagrange) fsLock.Unlock() diff --git a/test/unsafekzg/options.go b/test/unsafekzg/options.go index b4a7323050..76572455b4 100644 --- a/test/unsafekzg/options.go +++ b/test/unsafekzg/options.go @@ -3,11 +3,12 @@ package unsafekzg import ( "crypto/sha256" "errors" + "log/slog" "math/big" "os" "path/filepath" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" ) // Option allows changing the behaviour of the unsafe KZG SRS generation. @@ -99,7 +100,7 @@ func initCache(cacheDir string) { log := logger.Logger() // populate cache from disk - log.Warn().Str("cacheDir", cacheDir).Msg("using kzg srs cache") + log.Warn("using kzg srs cache", slog.String("cacheDir", cacheDir)) if _, err := os.Stat(cacheDir); os.IsNotExist(err) { err := os.MkdirAll(cacheDir, 0700) From 80035a2316dbd0fa77e434a1bc8bc8c856111c0d Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:17:57 +0000 Subject: [PATCH 25/44] feat: suppress logs in fuzzing test --- test/solver_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/solver_test.go b/test/solver_test.go index dc27a645a8..4573dedf0c 100644 --- a/test/solver_test.go +++ b/test/solver_test.go @@ -3,6 +3,7 @@ package test import ( "fmt" "io" + "log/slog" "math/big" "reflect" "strconv" @@ -187,7 +188,7 @@ func formatWitness(witness []tinyfield.Element) string { func (p *permutter) solve(i int) error { pw := newPermutterWitness(p.witness) - _, err := p.constraintSystems[i].Solve(pw, solver.WithHints(p.hints...)) + _, err := p.constraintSystems[i].Solve(pw, solver.WithLogger[*slog.Logger](nil), solver.WithHints(p.hints...)) return err } From 7810dcbe8239b719cdab5d438f37e07c995b66a4 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:18:41 +0000 Subject: [PATCH 26/44] fix: skip solver consistency for U64-only circuit --- test/solver_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/solver_test.go b/test/solver_test.go index 4573dedf0c..6cc3a44855 100644 --- a/test/solver_test.go +++ b/test/solver_test.go @@ -53,6 +53,12 @@ func TestSolverConsistency(t *testing.T) { return } tc := circuits.Circuits[name] + if tc.U64Only { + // skip circuits that are not compatible with tinyfield, as the + // goal of this test is to flag potential solver issues, and not + // to test tinyfield itself. + return + } t.Parallel() err := consistentSolver(tc.Circuit, tc.HintFunctions) if err != nil { From 627ab0f8cbebee8206fb48eaa21981a7e7d3bdd2 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:21:54 +0000 Subject: [PATCH 27/44] feat: provide logger in assert method --- test/assert_options.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/assert_options.go b/test/assert_options.go index 9f74c0eef5..3aed7bf635 100644 --- a/test/assert_options.go +++ b/test/assert_options.go @@ -1,6 +1,7 @@ package test import ( + "log/slog" "testing" "github.com/consensys/gnark-crypto/ecc" @@ -8,6 +9,7 @@ import ( "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/frontend" + "github.com/consensys/gnark/internal/logger" ) // TestingOption defines option for altering the behavior of Assert methods. @@ -25,6 +27,8 @@ type testingConfig struct { validAssignments []frontend.Circuit invalidAssignments []frontend.Circuit + + logger *slog.Logger } // default options @@ -51,6 +55,7 @@ func (assert *Assert) options(opts ...TestingOption) testingConfig { if smallfieldTestFlag { opt.checkSmallField = true } + opt.logger = logger.Logger() // apply user provided options. for _, option := range opts { @@ -227,3 +232,15 @@ func WithoutCurveChecks() TestingOption { return nil } } + +// WithLogger sets the logger used by the assertions. If this option is not +// provided, then the default logger is used. Passing nil disables logging. +func WithLogger(log *slog.Logger) TestingOption { + return func(opt *testingConfig) error { + if log == nil { + log = logger.DisabledLogger() + } + opt.logger = log + return nil + } +} From c209e5853aae91f1ea7e2ab58bc87aaf16ea8c79 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:44:13 +0000 Subject: [PATCH 28/44] feat: add trace logs in assertions --- test/assert_checkcircuit.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/test/assert_checkcircuit.go b/test/assert_checkcircuit.go index f7d91554c1..641d215734 100644 --- a/test/assert_checkcircuit.go +++ b/test/assert_checkcircuit.go @@ -1,6 +1,7 @@ package test import ( + "log/slog" "math/big" "github.com/consensys/gnark-crypto/ecc" @@ -13,7 +14,7 @@ import ( "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/schema" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/test/unsafekzg" ) @@ -35,13 +36,13 @@ import ( func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOption) { // get the testing configuration opt := assert.options(opts...) - log := logger.Logger() // for each {curve, backend} tuple for _, curve := range opt.curves { // run in sub-test to contextualize with curve assert.Run(func(assert *Assert) { + log := opt.logger.With(slog.String("curve", curve.String())) // parse valid / invalid assignments var invalidWitnesses, validWitnesses []_witness @@ -51,6 +52,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti // check that the assignment is valid with the test engine if !opt.skipTestEngine { + logger.Trace(log, "checking valid assignment with test engine") err := IsSolved(circuit, w.assignment, curve.ScalarField()) assert.noError(curve.ScalarField(), err, &w) } @@ -62,6 +64,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti // check that the assignment is invalid with the test engine if !opt.skipTestEngine { + logger.Trace(log, "checking invalid assignment with test engine") err := IsSolved(circuit, w.assignment, curve.ScalarField()) assert.error(curve.ScalarField(), err, &w) } @@ -72,8 +75,10 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti // run in sub-test to contextualize with backend assert.Run(func(assert *Assert) { + log := log.With(slog.String("backend", b.String())) // 1- check that the circuit compiles + logger.Trace(log, "checking circuit compilation") ccs, err := assert.compile(circuit, curve.ScalarField(), b, opt.compileOpts) assert.noError(curve.ScalarField(), err, nil) @@ -84,6 +89,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti if !opt.checkProver { for _, w := range invalidWitnesses { assert.Run(func(assert *Assert) { + logger.Trace(log, "checking invalid assignment with constraint system solver") _, err = ccs.Solve(w.full, opt.solverOpts...) assert.error(curve.ScalarField(), err, &w) }, "invalid_witness") @@ -91,6 +97,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti for _, w := range validWitnesses { assert.Run(func(assert *Assert) { + logger.Trace(log, "checking valid assignment with constraint system solver") _, err = ccs.Solve(w.full, opt.solverOpts...) assert.noError(curve.ScalarField(), err, &w) }, "valid_witness") @@ -116,6 +123,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti } // proof system setup. + logger.Trace(log, "running setup for backend") pk, vk, pkBuilder, vkBuilder, proofBuilder, err := concreteBackend.setup(ccs, curve) assert.noError(curve.ScalarField(), err, nil) @@ -128,18 +136,18 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti if b == backend.GROTH16 { // currently groth16 Solidity checker only supports circuits with up to 1 commitment if len(ccs.GetCommitments().CommitmentIndexes()) > 1 { - log.Warn(). - Int("nb_commitments", len(ccs.GetCommitments().CommitmentIndexes())). - Msg("skipping solidity check, too many commitments") + log.Warn("skipping solidity check, too many commitments", slog.Int("nb_commitments", len(ccs.GetCommitments().CommitmentIndexes()))) } checkSolidity = checkSolidity && (len(ccs.GetCommitments().CommitmentIndexes()) <= 1) // set the default hash function in case of custom hash function not set. This is to ensure that the proof can be verified by gnark-solidity-checker proverOpts = append([]backend.ProverOption{solidity.WithProverTargetSolidityVerifier(b)}, opt.proverOpts...) verifierOpts = append([]backend.VerifierOption{solidity.WithVerifierTargetSolidityVerifier(b)}, opt.verifierOpts...) } + logger.Trace(log, "running prover with valid witness") proof, err := concreteBackend.prove(ccs, pk, w.full, proverOpts...) assert.noError(curve.ScalarField(), err, &w) + logger.Trace(log, "running verifier") err = concreteBackend.verify(proof, vk, w.public, verifierOpts...) assert.noError(curve.ScalarField(), err, &w) @@ -147,12 +155,14 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti // check that the proof can be verified by gnark-solidity-checker if _vk, ok := vk.(solidity.VerifyingKey); ok { assert.Run(func(assert *Assert) { + logger.Trace(log, "running Solidity verification") assert.solidityVerification(b, curve, _vk, proof, w.public, opt.solidityOpts) }, "solidity") } } // check proof serialization + logger.Trace(log, "checking proof serialization") assert.roundTripCheck(proof, proofBuilder, "proof") }, "valid_witness") } @@ -160,6 +170,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti // for each invalid witness, run the prover only, it should fail. for _, w := range invalidWitnesses { assert.Run(func(assert *Assert) { + logger.Trace(log, "checking invalid assignment with prover") _, err := concreteBackend.prove(ccs, pk, w.full, opt.proverOpts...) assert.error(curve.ScalarField(), err, &w) }, "invalid_witness") @@ -167,6 +178,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti // check serialization of proving and verifying keys if opt.checkSerialization && ccs.GetNbConstraints() <= serializationThreshold && (curve == ecc.BN254 || curve == ecc.BLS12_381) { + logger.Trace(log, "checking serialization of proving and verifying keys") assert.roundTripCheck(pk, pkBuilder, "proving_key") assert.roundTripCheck(vk, vkBuilder, "verifying_key") } From ee920c7464e0caf48bec6c26b4e2532be3887dcb Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:48:39 +0000 Subject: [PATCH 29/44] feat: use assert logger in Solidity logs --- test/assert_checkcircuit.go | 2 +- test/assert_solidity.go | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/assert_checkcircuit.go b/test/assert_checkcircuit.go index 641d215734..943b7be3a1 100644 --- a/test/assert_checkcircuit.go +++ b/test/assert_checkcircuit.go @@ -156,7 +156,7 @@ func (assert *Assert) CheckCircuit(circuit frontend.Circuit, opts ...TestingOpti if _vk, ok := vk.(solidity.VerifyingKey); ok { assert.Run(func(assert *Assert) { logger.Trace(log, "running Solidity verification") - assert.solidityVerification(b, curve, _vk, proof, w.public, opt.solidityOpts) + assert.solidityVerification(b, curve, _vk, proof, w.public, opt.solidityOpts, log) }, "solidity") } } diff --git a/test/assert_solidity.go b/test/assert_solidity.go index 4214bd6c68..a7a75b63b0 100644 --- a/test/assert_solidity.go +++ b/test/assert_solidity.go @@ -2,6 +2,7 @@ package test import ( "encoding/hex" + "log/slog" "os" "os/exec" "path/filepath" @@ -22,6 +23,7 @@ func (assert *Assert) solidityVerification(b backend.ID, c ecc.ID, vk solidity.V proof any, validPublicWitness witness.Witness, opts []solidity.ExportOption, + log *slog.Logger, ) { if !SolcCheck { // we return, we don't have the solidity check build tag defined @@ -37,7 +39,7 @@ func (assert *Assert) solidityVerification(b backend.ID, c ecc.ID, vk solidity.V panic("solidity verification not implemented for this curve: " + c.String()) } if nbPubWit == 0 { - assert.Log("skipping solidity tests for zero public witness length") + log.Warn("skipping solidity tests for zero public witness length") return } @@ -65,7 +67,7 @@ func (assert *Assert) solidityVerification(b backend.ID, c ecc.ID, vk solidity.V // generate assets // gnark-solidity-checker generate --dir tmpdir --solidity contract_g16.sol cmd := exec.Command("go", "tool", "gnark-solidity-checker", "generate", "--dir", tmpDir, "--solidity", "gnark_verifier.sol") - assert.Log("running ", cmd.String()) + log.Debug("generating assets with gnark-solidity-checker", slog.String("cmd", cmd.String())) out, err := cmd.CombinedOutput() assert.NoError(err, string(out)) @@ -122,7 +124,7 @@ func (assert *Assert) solidityVerification(b backend.ID, c ecc.ID, vk solidity.V // verify proof // gnark-solidity-checker verify --dir tmdir --groth16 --nb-public-inputs 1 --proof 1234 --public-inputs dead cmd = exec.Command("go", checkerOpts...) - assert.Log("running ", cmd.String()) + log.Debug("running gnark-solidity-checker verify", slog.String("cmd", cmd.String())) out, err = cmd.CombinedOutput() assert.NoError(err, string(out)) } From d612a67208bbc3b89d11d550cf0249ecae4f7934 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 19 May 2026 23:49:17 +0000 Subject: [PATCH 30/44] test: update debug test --- debug_test.go | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/debug_test.go b/debug_test.go index e5b543d9ee..296fbe7650 100644 --- a/debug_test.go +++ b/debug_test.go @@ -2,6 +2,7 @@ package gnark_test import ( "bytes" + "log/slog" "math/big" "testing" @@ -15,7 +16,6 @@ import ( "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/frontend/cs/scs" "github.com/consensys/gnark/test/unsafekzg" - "github.com/rs/zerolog" "github.com/stretchr/testify/require" ) @@ -48,11 +48,11 @@ func TestPrintln(t *testing.T) { witness.B = 11 var expected bytes.Buffer - expected.WriteString("debug_test.go:30 > 13 is the addition\n") - expected.WriteString("debug_test.go:32 > 26 42\n") - expected.WriteString("debug_test.go:34 > bits 1\n") - expected.WriteString("debug_test.go:35 > circuit {A: 2, B: 11}\n") - expected.WriteString("debug_test.go:39 > m .*\n") + expected.WriteString("msg=api.Println source=debug_test.go:30 debug=\"13 is the addition\"\n") + expected.WriteString("msg=api.Println source=debug_test.go:32 debug=\"26 42\"\n") + expected.WriteString("msg=api.Println source=debug_test.go:34 debug=\"bits 1\"\n") + expected.WriteString("msg=api.Println source=debug_test.go:35 debug=\"circuit {A: 2, B: 11}\"\n") + expected.WriteString("msg=api.Println source=debug_test.go:39 debug=\"m .*\"\n") { trace, _ := getGroth16Trace(&circuit, &witness) @@ -177,7 +177,18 @@ func getPlonkTrace(circuit, w frontend.Circuit) (string, error) { if err != nil { return "", err } - log := zerolog.New(&zerolog.ConsoleWriter{Out: &buf, NoColor: true, PartsExclude: []string{zerolog.LevelFieldName, zerolog.TimestampFieldName}}) + log := slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{ + Level: slog.LevelDebug, + ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { + if a.Key == slog.TimeKey && a.Value.Kind() == slog.KindTime { + return slog.Attr{} + } + if a.Key == slog.LevelKey && a.Value.Kind() == slog.KindAny { + return slog.Attr{} + } + return a + }, + })) _, err = plonk.Prove(ccs, pk, sw, backend.WithSolverOptions(solver.WithLogger(log))) return buf.String(), err } @@ -198,7 +209,18 @@ func getGroth16Trace(circuit, w frontend.Circuit) (string, error) { if err != nil { return "", err } - log := zerolog.New(&zerolog.ConsoleWriter{Out: &buf, NoColor: true, PartsExclude: []string{zerolog.LevelFieldName, zerolog.TimestampFieldName}}) + log := slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{ + Level: slog.LevelDebug, + ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { + if a.Key == slog.TimeKey && a.Value.Kind() == slog.KindTime { + return slog.Attr{} + } + if a.Key == slog.LevelKey && a.Value.Kind() == slog.KindAny { + return slog.Attr{} + } + return a + }, + })) _, err = groth16.Prove(ccs, pk, sw, backend.WithSolverOptions(solver.WithLogger(log))) return buf.String(), err } From 022e64488c68d2022f39f4845a5d9e5ba9c58273 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 07:39:10 +0000 Subject: [PATCH 31/44] feat: remove format declarations --- std/rangecheck/rangecheck_commit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/rangecheck/rangecheck_commit.go b/std/rangecheck/rangecheck_commit.go index 90b11cd68c..45f3b91394 100644 --- a/std/rangecheck/rangecheck_commit.go +++ b/std/rangecheck/rangecheck_commit.go @@ -48,7 +48,7 @@ func newCommitRangechecker(api frontend.API, opts ...Option) *commitChecker { if cht, ok := ch.(*commitChecker); ok { if cfg.baseLength > 0 && cht.cfg.baseLength != cfg.baseLength { if cht.cfg.baseLength > 0 { - api.Compiler().Logger().Warn("rangechecker: existing checker has base length %d, requested %d. overwriting", slog.Int("existingBaseLength", cht.cfg.baseLength), slog.Int("requestedBaseLength", cfg.baseLength)) + api.Compiler().Logger().Warn("rangechecker: overwriting existing base length", slog.Int("existingBaseLength", cht.cfg.baseLength), slog.Int("requestedBaseLength", cfg.baseLength)) } cht.cfg.baseLength = cfg.baseLength } From b0aa05859276eb34b55a2e9ec6dbe54e81fff9a2 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 07:42:06 +0000 Subject: [PATCH 32/44] docs: update compilelogger interface --- internal/compilelogger/compilelogger.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/compilelogger/compilelogger.go b/internal/compilelogger/compilelogger.go index 46ee6eccfb..a8d8a5eae2 100644 --- a/internal/compilelogger/compilelogger.go +++ b/internal/compilelogger/compilelogger.go @@ -22,7 +22,8 @@ type compileLoggerKey struct { // Recommended identifier format is "component/feature" to allow filtering by // component and grouping related messages together. // -// msg can be a format string and args are the corresponding arguments, as in logger.Logger().Msgf(msg, args...). +// msg and args are passed directly to the logger, allowing for structured +// logging. See [slog.Logger.Log] for details on supported formats. // // LogOnce panics if the api does not implement [kvstore.Store], which should // never happen since the compiler is expected to implement it. From d1a9c1296d1f4626c8df7a6edf4ed32e97f49d6c Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 08:03:08 +0000 Subject: [PATCH 33/44] feat: add slog linter --- .golangci.yml | 10 ++++++++++ internal/compilelogger/compilelogger.go | 1 + internal/logger/logger.go | 1 + internal/logger/zerolog.go | 1 + 4 files changed, 13 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 7940a03693..75a3cedf00 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,6 +9,7 @@ linters: - govet - ineffassign - misspell + - sloglint settings: staticcheck: checks: @@ -20,6 +21,15 @@ linters: excludes: - G115 - G602 + sloglint: + attr-only: true + no-mixed-args: true + static-msg: true + no-global: all + custom-funcs: + - name: github.com/consensys/gnark/internal/logger.Trace + msg-pos: 1 + args-pos: 2 exclusions: generated: disable presets: diff --git a/internal/compilelogger/compilelogger.go b/internal/compilelogger/compilelogger.go index a8d8a5eae2..d93460ee41 100644 --- a/internal/compilelogger/compilelogger.go +++ b/internal/compilelogger/compilelogger.go @@ -39,5 +39,6 @@ func LogOnce(api frontend.Compiler, level slog.Level, identifier, msg string, ar // set the key to avoid logging again with the same identifier kv.SetKeyValue(key, struct{}{}) + //nolint:sloglint // LogOnce is a compile-time logging wrapper; call sites are responsible for static messages and attrs. api.Logger().Log(context.Background(), level, msg, args...) } diff --git a/internal/logger/logger.go b/internal/logger/logger.go index b0b2a6f7d2..2f4ccffd73 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -51,6 +51,7 @@ func DisabledLogger() *slog.Logger { } func Trace(log *slog.Logger, msg string, attrs ...slog.Attr) { + //nolint:sloglint // Trace is the package-level wrapper that validates call sites via sloglint custom-funcs. log.LogAttrs(context.Background(), LevelTrace, msg, attrs...) } diff --git a/internal/logger/zerolog.go b/internal/logger/zerolog.go index 7d6aa4dc59..1bf9cce67f 100644 --- a/internal/logger/zerolog.go +++ b/internal/logger/zerolog.go @@ -123,6 +123,7 @@ func (w slogLevelWriter) Write(p []byte) (int, error) { func (w slogLevelWriter) WriteLevel(level zerolog.Level, p []byte) (int, error) { level, msg, attrs := decodeZerologEvent(level, p) + //nolint:sloglint // The compatibility bridge forwards messages decoded from zerolog events. w.logger.LogAttrs(context.Background(), slogLevel(level), msg, attrs...) return len(p), nil } From 4ce496e843f4cfb3b5e3143b4401e50e81de6cec Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 08:21:25 +0000 Subject: [PATCH 34/44] chore: update golangci-lint to latest to have new slog linter --- .github/workflows/pr.yml | 2 +- .github/workflows/push.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 404f9b0cca..3668e07a44 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -11,7 +11,7 @@ permissions: env: ABIGEN_VERSION: v1.14.8 GO_VERSION: 1.25.x # NB! when updating also update matrix, we cannot refer to env variables in the matrix - GOLANGCI_LINT_VERSION: v2.10.1 + GOLANGCI_LINT_VERSION: v2.12.2 jobs: staticcheck: diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 234fa06255..902c62f93b 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -14,7 +14,7 @@ permissions: env: ABIGEN_VERSION: v1.14.8 GO_VERSION: 1.25.x # NB! when updating also update matrix, we cannot refer to env variables in the matrix - GOLANGCI_LINT_VERSION: v2.10.1 + GOLANGCI_LINT_VERSION: v2.12.2 jobs: staticcheck: From 6f6a6b7c1af27cc79ae523a5f25484ab36533323 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 08:21:40 +0000 Subject: [PATCH 35/44] chore: run go fix --- debug/debug_set.go | 1 - debug/debug_unset.go | 1 - frontend/compile.go | 2 +- frontend/schema/internal/reflectwalk/reflectwalk.go | 4 ++-- frontend/schema/schema.go | 2 +- test/assert.go | 2 +- 6 files changed, 5 insertions(+), 7 deletions(-) diff --git a/debug/debug_set.go b/debug/debug_set.go index 49e94a0755..3ec7c7ebf6 100644 --- a/debug/debug_set.go +++ b/debug/debug_set.go @@ -1,5 +1,4 @@ //go:build debug -// +build debug package debug diff --git a/debug/debug_unset.go b/debug/debug_unset.go index fe1628f492..d816916477 100644 --- a/debug/debug_unset.go +++ b/debug/debug_unset.go @@ -1,5 +1,4 @@ //go:build !debug -// +build !debug package debug diff --git a/frontend/compile.go b/frontend/compile.go index f91ff3aac6..d9eba68f75 100644 --- a/frontend/compile.go +++ b/frontend/compile.go @@ -112,7 +112,7 @@ func CompileGeneric[E constraint.Element](field *big.Int, newBuilder NewBuilderG func parseCircuit[E constraint.Element](builder Builder[E], circuit Circuit) (err error) { // ensure circuit.Define has pointer receiver - if reflect.ValueOf(circuit).Kind() != reflect.Ptr { + if reflect.ValueOf(circuit).Kind() != reflect.Pointer { return errors.New("frontend.Circuit methods must be defined on pointer receiver") } diff --git a/frontend/schema/internal/reflectwalk/reflectwalk.go b/frontend/schema/internal/reflectwalk/reflectwalk.go index 9de94c87d1..a54c0628f6 100644 --- a/frontend/schema/internal/reflectwalk/reflectwalk.go +++ b/frontend/schema/internal/reflectwalk/reflectwalk.go @@ -121,7 +121,7 @@ func walk(v reflect.Value, w interface{}) (err error) { pointerV = pointerV.Elem() } - if pointerV.Kind() == reflect.Ptr { + if pointerV.Kind() == reflect.Pointer { if pw, ok := w.(PointerValueWalker); ok { if err = pw.Pointer(pointerV); err != nil { if err == ErrSkipEntry { @@ -143,7 +143,7 @@ func walk(v reflect.Value, w interface{}) (err error) { // If we still have a pointer or interface we have to indirect another level. switch pointerV.Kind() { - case reflect.Ptr, reflect.Interface: + case reflect.Pointer, reflect.Interface: continue } break diff --git a/frontend/schema/schema.go b/frontend/schema/schema.go index 46518385e7..8bc0211169 100644 --- a/frontend/schema/schema.go +++ b/frontend/schema/schema.go @@ -183,7 +183,7 @@ func parse(r []Field, input interface{}, target reflect.Type, parentFullName, pa tValue := reflect.ValueOf(input) // get pointed value if needed - if tValue.Kind() == reflect.Ptr { + if tValue.Kind() == reflect.Pointer { tValue = tValue.Elem() } diff --git a/test/assert.go b/test/assert.go index 1cfc56040b..8981a6bec5 100644 --- a/test/assert.go +++ b/test/assert.go @@ -77,7 +77,7 @@ func deepEqualMismatchValue(a, b reflect.Value, path string) (string, string, st } switch a.Kind() { - case reflect.Ptr: + case reflect.Pointer: if a.IsNil() && b.IsNil() { return "", "", "" } From 164ec57e8983d3307cda42bf38808f8dde3c8a8f Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 09:32:29 +0000 Subject: [PATCH 36/44] feat: use infinity for unset gomemlimit --- internal/logger/logger.go | 10 +++++++++- internal/logger/logger_test.go | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 2f4ccffd73..9d6b356810 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -5,6 +5,7 @@ import ( "context" "io" "log/slog" + "math" "os" "runtime" runtimedebug "runtime/debug" @@ -116,7 +117,7 @@ func logDebugRuntimeInfo(log *slog.Logger) { func runtimeInfoAttrs(buildInfo *runtimedebug.BuildInfo) []slog.Attr { attrs := []slog.Attr{ slog.Int("gomaxprocs", runtime.GOMAXPROCS(0)), - slog.Int64("gomemlimit", runtimedebug.SetMemoryLimit(-1)), + gomemlimitAttr(runtimedebug.SetMemoryLimit(-1)), slog.String("goarch", runtime.GOARCH), slog.String("goos", runtime.GOOS), slog.Bool("support_neon", cpu.SupportNEON), @@ -138,6 +139,13 @@ func runtimeInfoAttrs(buildInfo *runtimedebug.BuildInfo) []slog.Attr { return attrs } +func gomemlimitAttr(limit int64) slog.Attr { + if limit == math.MaxInt64 { + return slog.String("gomemlimit", "∞") + } + return slog.Int64("gomemlimit", limit) +} + func buildSetting(buildInfo *runtimedebug.BuildInfo, key string) string { if buildInfo == nil { return "" diff --git a/internal/logger/logger_test.go b/internal/logger/logger_test.go index 91b723d8e1..0011e80dd8 100644 --- a/internal/logger/logger_test.go +++ b/internal/logger/logger_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "log/slog" + "math" "os" "runtime" "strings" @@ -149,6 +150,18 @@ func TestLoggerDebugLevelEmitsRuntimeInfo(t *testing.T) { } } +func TestGOMEMLIMITAttrUsesInfinityForUnlimitedMemory(t *testing.T) { + attr := gomemlimitAttr(math.MaxInt64) + if attr.Value.Kind() != slog.KindString || attr.Value.String() != "∞" { + t.Fatalf("expected unlimited gomemlimit to be rendered as infinity, got %s", attr) + } + + attr = gomemlimitAttr(1024) + if attr.Value.Kind() != slog.KindInt64 || attr.Value.Int64() != 1024 { + t.Fatalf("expected finite gomemlimit to remain an int64, got %s", attr) + } +} + func TestLoggerTraceLevelEmitsSource(t *testing.T) { var buf bytes.Buffer withLoggerOutput(t, &buf) From adff36705afa60abe4ea74b1018bc9fceca0743b Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 10:41:09 +0000 Subject: [PATCH 37/44] fix: ensure trace logs source line --- internal/logger/logger.go | 13 +++++++++++-- internal/logger/logger_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 9d6b356810..d5eb7f27c0 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -11,6 +11,7 @@ import ( runtimedebug "runtime/debug" "strings" "sync" + "time" "github.com/consensys/gnark" "github.com/consensys/gnark-crypto/utils/cpu" @@ -52,8 +53,16 @@ func DisabledLogger() *slog.Logger { } func Trace(log *slog.Logger, msg string, attrs ...slog.Attr) { - //nolint:sloglint // Trace is the package-level wrapper that validates call sites via sloglint custom-funcs. - log.LogAttrs(context.Background(), LevelTrace, msg, attrs...) + ctx := context.Background() + if !log.Enabled(ctx, LevelTrace) { + return + } + + var pcs [1]uintptr + runtime.Callers(2, pcs[:]) + record := slog.NewRecord(time.Now(), LevelTrace, msg, pcs[0]) + record.AddAttrs(attrs...) + _ = log.Handler().Handle(ctx, record) } func newHandler(w io.Writer, level slog.Level) slog.Handler { diff --git a/internal/logger/logger_test.go b/internal/logger/logger_test.go index 0011e80dd8..d147a042d5 100644 --- a/internal/logger/logger_test.go +++ b/internal/logger/logger_test.go @@ -178,6 +178,35 @@ func TestLoggerTraceLevelEmitsSource(t *testing.T) { } } +func TestTraceUsesCallerSource(t *testing.T) { + var buf bytes.Buffer + withLoggerOutput(t, &buf) + t.Setenv(EnvLevel, "trace") + + Trace(Logger(), "visible") + + output := buf.String() + traceLine := lineContaining(output, "msg=visible") + if traceLine == "" { + t.Fatalf("expected visible trace line, got %q", output) + } + if !strings.Contains(traceLine, "source=") || !strings.Contains(traceLine, "logger_test.go") { + t.Fatalf("expected trace source to point at test caller, got %q", output) + } + if strings.Contains(traceLine, "internal/logger/logger.go") { + t.Fatalf("trace source should not point at logger.Trace wrapper, got %q", output) + } +} + +func lineContaining(output, substr string) string { + for _, line := range strings.Split(output, "\n") { + if strings.Contains(line, substr) { + return line + } + } + return "" +} + func withLoggerOutput(t *testing.T, w *bytes.Buffer) { t.Helper() From ea435c9d3cd7f966e7073a4d4cd5aef11549ad2d Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 11:02:32 +0000 Subject: [PATCH 38/44] feat: add tracing logs in backends --- backend/groth16/bls12-377/prove.go | 21 ++++++++ backend/groth16/bls12-381/prove.go | 21 ++++++++ backend/groth16/bn254/prove.go | 21 ++++++++ backend/groth16/bw6-761/prove.go | 21 ++++++++ backend/plonk/bls12-377/prove.go | 53 +++++++++++++++++++ backend/plonk/bls12-381/prove.go | 53 +++++++++++++++++++ backend/plonk/bn254/prove.go | 53 +++++++++++++++++++ backend/plonk/bw6-761/prove.go | 53 +++++++++++++++++++ .../zkpschemes/groth16/groth16.prove.go.tmpl | 21 ++++++++ .../zkpschemes/plonk/plonk.prove.go.tmpl | 53 +++++++++++++++++++ 10 files changed, 370 insertions(+) diff --git a/backend/groth16/bls12-377/prove.go b/backend/groth16/bls12-377/prove.go index 8f948b6b81..c966973a0a 100644 --- a/backend/groth16/bls12-377/prove.go +++ b/backend/groth16/bls12-377/prove.go @@ -19,6 +19,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/hash_to_field" "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bls12-377" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/backend" @@ -101,15 +102,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil })) + solveStart := time.Now() _solution, err := r1cs.Solve(fullWitness, solverOpts...) if err != nil { return nil, err } + logger.Trace(log, "solving done", slog.Duration("took", time.Since(solveStart))) solution := _solution.(*cs.R1CSSolution) wireValues := []fr.Element(solution.W) start := time.Now() + commitmentStart := time.Now() poks := make([]curve.G1Affine, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { @@ -130,12 +134,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b if _, err = proof.CommitmentPok.Fold(poks, challenge[0], ecc.MultiExpConfig{NbTasks: 1}); err != nil { return nil, err } + logger.Trace(log, "commitment proof of knowledge", slog.Duration("took", time.Since(commitmentStart)), slog.Int("nbCommitments", len(pk.CommitmentKeys))) // H (witness reduction / FFT part) var h []fr.Element chHDone := make(chan struct{}, 1) go func() { + hStart := time.Now() h = computeH(solution.A, solution.B, solution.C, &pk.Domain) + logger.Trace(log, "computeH", slog.Duration("took", time.Since(hStart)), slog.Int("size", len(h))) solution.A = nil solution.B = nil solution.C = nil @@ -194,11 +201,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chBs1Done := make(chan error, 1) computeBS1 := func() { <-chWireValuesB + msmStart := time.Now() if _, err := bs1.MultiExp(pk.G1.B, wireValuesB, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chBs1Done <- err close(chBs1Done) return } + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB))) bs1.AddMixed(&pk.G1.Beta) bs1.AddMixed(&deltas[1]) chBs1Done <- nil @@ -207,11 +216,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chArDone := make(chan error, 1) computeAR1 := func() { <-chWireValuesA + msmStart := time.Now() if _, err := ar.MultiExp(pk.G1.A, wireValuesA, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chArDone <- err close(chArDone) return } + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesA))) ar.AddMixed(&pk.G1.Alpha) ar.AddMixed(&deltas[0]) proof.Ar.FromJacobian(&ar) @@ -227,7 +238,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chKrs2Done := make(chan error, 1) sizeH := int(pk.Domain.Cardinality - 1) // comes from the fact the deg(H)=(n-1)+(n-1)-n=n-2 go func() { + msmStart := time.Now() _, err := krs2.MultiExp(pk.G1.Z, h[:sizeH], ecc.MultiExpConfig{NbTasks: n / 2}) + if err == nil { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", sizeH)) + } chKrs2Done <- err }() @@ -235,12 +250,16 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b // TODO Perf @Tabaie worst memory allocation offender toRemove := commitmentInfo.GetPrivateCommitted() toRemove = append(toRemove, commitmentInfo.CommitmentIndexes()) + filterStart := time.Now() _wireValues := filterHeap(wireValues[r1cs.GetNbPublicVariables():], r1cs.GetNbPublicVariables(), internal.ConcatAll(toRemove...)) + logger.Trace(log, "filter wire values", slog.Duration("took", time.Since(filterStart)), slog.Int("size", len(_wireValues))) + msmStart := time.Now() if _, err := krs.MultiExp(pk.G1.K, _wireValues, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chKrsDone <- err return } + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(_wireValues))) krs.AddMixed(&deltas[2]) n := 3 for n != 0 { @@ -283,10 +302,12 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b nbTasks *= 2 } <-chWireValuesB + msmStart := time.Now() if _, err := Bs.MultiExp(pk.G2.B, wireValuesB, ecc.MultiExpConfig{NbTasks: nbTasks}); err != nil { return err } + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB)), slog.Int("nbTasks", nbTasks)) deltaS.FromAffine(&pk.G2.Delta) deltaS.ScalarMultiplication(&deltaS, &s) Bs.AddAssign(&deltaS) diff --git a/backend/groth16/bls12-381/prove.go b/backend/groth16/bls12-381/prove.go index d56f13c205..22f1b11095 100644 --- a/backend/groth16/bls12-381/prove.go +++ b/backend/groth16/bls12-381/prove.go @@ -19,6 +19,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/hash_to_field" "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bls12-381" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/backend" @@ -101,15 +102,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil })) + solveStart := time.Now() _solution, err := r1cs.Solve(fullWitness, solverOpts...) if err != nil { return nil, err } + logger.Trace(log, "solving done", slog.Duration("took", time.Since(solveStart))) solution := _solution.(*cs.R1CSSolution) wireValues := []fr.Element(solution.W) start := time.Now() + commitmentStart := time.Now() poks := make([]curve.G1Affine, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { @@ -130,12 +134,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b if _, err = proof.CommitmentPok.Fold(poks, challenge[0], ecc.MultiExpConfig{NbTasks: 1}); err != nil { return nil, err } + logger.Trace(log, "commitment proof of knowledge", slog.Duration("took", time.Since(commitmentStart)), slog.Int("nbCommitments", len(pk.CommitmentKeys))) // H (witness reduction / FFT part) var h []fr.Element chHDone := make(chan struct{}, 1) go func() { + hStart := time.Now() h = computeH(solution.A, solution.B, solution.C, &pk.Domain) + logger.Trace(log, "computeH", slog.Duration("took", time.Since(hStart)), slog.Int("size", len(h))) solution.A = nil solution.B = nil solution.C = nil @@ -194,11 +201,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chBs1Done := make(chan error, 1) computeBS1 := func() { <-chWireValuesB + msmStart := time.Now() if _, err := bs1.MultiExp(pk.G1.B, wireValuesB, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chBs1Done <- err close(chBs1Done) return } + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB))) bs1.AddMixed(&pk.G1.Beta) bs1.AddMixed(&deltas[1]) chBs1Done <- nil @@ -207,11 +216,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chArDone := make(chan error, 1) computeAR1 := func() { <-chWireValuesA + msmStart := time.Now() if _, err := ar.MultiExp(pk.G1.A, wireValuesA, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chArDone <- err close(chArDone) return } + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesA))) ar.AddMixed(&pk.G1.Alpha) ar.AddMixed(&deltas[0]) proof.Ar.FromJacobian(&ar) @@ -227,7 +238,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chKrs2Done := make(chan error, 1) sizeH := int(pk.Domain.Cardinality - 1) // comes from the fact the deg(H)=(n-1)+(n-1)-n=n-2 go func() { + msmStart := time.Now() _, err := krs2.MultiExp(pk.G1.Z, h[:sizeH], ecc.MultiExpConfig{NbTasks: n / 2}) + if err == nil { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", sizeH)) + } chKrs2Done <- err }() @@ -235,12 +250,16 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b // TODO Perf @Tabaie worst memory allocation offender toRemove := commitmentInfo.GetPrivateCommitted() toRemove = append(toRemove, commitmentInfo.CommitmentIndexes()) + filterStart := time.Now() _wireValues := filterHeap(wireValues[r1cs.GetNbPublicVariables():], r1cs.GetNbPublicVariables(), internal.ConcatAll(toRemove...)) + logger.Trace(log, "filter wire values", slog.Duration("took", time.Since(filterStart)), slog.Int("size", len(_wireValues))) + msmStart := time.Now() if _, err := krs.MultiExp(pk.G1.K, _wireValues, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chKrsDone <- err return } + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(_wireValues))) krs.AddMixed(&deltas[2]) n := 3 for n != 0 { @@ -283,10 +302,12 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b nbTasks *= 2 } <-chWireValuesB + msmStart := time.Now() if _, err := Bs.MultiExp(pk.G2.B, wireValuesB, ecc.MultiExpConfig{NbTasks: nbTasks}); err != nil { return err } + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB)), slog.Int("nbTasks", nbTasks)) deltaS.FromAffine(&pk.G2.Delta) deltaS.ScalarMultiplication(&deltaS, &s) Bs.AddAssign(&deltaS) diff --git a/backend/groth16/bn254/prove.go b/backend/groth16/bn254/prove.go index 8dc176150d..0cd40e799a 100644 --- a/backend/groth16/bn254/prove.go +++ b/backend/groth16/bn254/prove.go @@ -19,6 +19,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fr/hash_to_field" "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bn254" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/backend" @@ -101,15 +102,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil })) + solveStart := time.Now() _solution, err := r1cs.Solve(fullWitness, solverOpts...) if err != nil { return nil, err } + logger.Trace(log, "solving done", slog.Duration("took", time.Since(solveStart))) solution := _solution.(*cs.R1CSSolution) wireValues := []fr.Element(solution.W) start := time.Now() + commitmentStart := time.Now() poks := make([]curve.G1Affine, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { @@ -130,12 +134,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b if _, err = proof.CommitmentPok.Fold(poks, challenge[0], ecc.MultiExpConfig{NbTasks: 1}); err != nil { return nil, err } + logger.Trace(log, "commitment proof of knowledge", slog.Duration("took", time.Since(commitmentStart)), slog.Int("nbCommitments", len(pk.CommitmentKeys))) // H (witness reduction / FFT part) var h []fr.Element chHDone := make(chan struct{}, 1) go func() { + hStart := time.Now() h = computeH(solution.A, solution.B, solution.C, &pk.Domain) + logger.Trace(log, "computeH", slog.Duration("took", time.Since(hStart)), slog.Int("size", len(h))) solution.A = nil solution.B = nil solution.C = nil @@ -194,11 +201,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chBs1Done := make(chan error, 1) computeBS1 := func() { <-chWireValuesB + msmStart := time.Now() if _, err := bs1.MultiExp(pk.G1.B, wireValuesB, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chBs1Done <- err close(chBs1Done) return } + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB))) bs1.AddMixed(&pk.G1.Beta) bs1.AddMixed(&deltas[1]) chBs1Done <- nil @@ -207,11 +216,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chArDone := make(chan error, 1) computeAR1 := func() { <-chWireValuesA + msmStart := time.Now() if _, err := ar.MultiExp(pk.G1.A, wireValuesA, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chArDone <- err close(chArDone) return } + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesA))) ar.AddMixed(&pk.G1.Alpha) ar.AddMixed(&deltas[0]) proof.Ar.FromJacobian(&ar) @@ -227,7 +238,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chKrs2Done := make(chan error, 1) sizeH := int(pk.Domain.Cardinality - 1) // comes from the fact the deg(H)=(n-1)+(n-1)-n=n-2 go func() { + msmStart := time.Now() _, err := krs2.MultiExp(pk.G1.Z, h[:sizeH], ecc.MultiExpConfig{NbTasks: n / 2}) + if err == nil { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", sizeH)) + } chKrs2Done <- err }() @@ -235,12 +250,16 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b // TODO Perf @Tabaie worst memory allocation offender toRemove := commitmentInfo.GetPrivateCommitted() toRemove = append(toRemove, commitmentInfo.CommitmentIndexes()) + filterStart := time.Now() _wireValues := filterHeap(wireValues[r1cs.GetNbPublicVariables():], r1cs.GetNbPublicVariables(), internal.ConcatAll(toRemove...)) + logger.Trace(log, "filter wire values", slog.Duration("took", time.Since(filterStart)), slog.Int("size", len(_wireValues))) + msmStart := time.Now() if _, err := krs.MultiExp(pk.G1.K, _wireValues, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chKrsDone <- err return } + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(_wireValues))) krs.AddMixed(&deltas[2]) n := 3 for n != 0 { @@ -283,10 +302,12 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b nbTasks *= 2 } <-chWireValuesB + msmStart := time.Now() if _, err := Bs.MultiExp(pk.G2.B, wireValuesB, ecc.MultiExpConfig{NbTasks: nbTasks}); err != nil { return err } + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB)), slog.Int("nbTasks", nbTasks)) deltaS.FromAffine(&pk.G2.Delta) deltaS.ScalarMultiplication(&deltaS, &s) Bs.AddAssign(&deltaS) diff --git a/backend/groth16/bw6-761/prove.go b/backend/groth16/bw6-761/prove.go index 2c4671e4bc..1aa9616bdf 100644 --- a/backend/groth16/bw6-761/prove.go +++ b/backend/groth16/bw6-761/prove.go @@ -19,6 +19,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/hash_to_field" "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bw6-761" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/backend" @@ -101,15 +102,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil })) + solveStart := time.Now() _solution, err := r1cs.Solve(fullWitness, solverOpts...) if err != nil { return nil, err } + logger.Trace(log, "solving done", slog.Duration("took", time.Since(solveStart))) solution := _solution.(*cs.R1CSSolution) wireValues := []fr.Element(solution.W) start := time.Now() + commitmentStart := time.Now() poks := make([]curve.G1Affine, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { @@ -130,12 +134,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b if _, err = proof.CommitmentPok.Fold(poks, challenge[0], ecc.MultiExpConfig{NbTasks: 1}); err != nil { return nil, err } + logger.Trace(log, "commitment proof of knowledge", slog.Duration("took", time.Since(commitmentStart)), slog.Int("nbCommitments", len(pk.CommitmentKeys))) // H (witness reduction / FFT part) var h []fr.Element chHDone := make(chan struct{}, 1) go func() { + hStart := time.Now() h = computeH(solution.A, solution.B, solution.C, &pk.Domain) + logger.Trace(log, "computeH", slog.Duration("took", time.Since(hStart)), slog.Int("size", len(h))) solution.A = nil solution.B = nil solution.C = nil @@ -194,11 +201,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chBs1Done := make(chan error, 1) computeBS1 := func() { <-chWireValuesB + msmStart := time.Now() if _, err := bs1.MultiExp(pk.G1.B, wireValuesB, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chBs1Done <- err close(chBs1Done) return } + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB))) bs1.AddMixed(&pk.G1.Beta) bs1.AddMixed(&deltas[1]) chBs1Done <- nil @@ -207,11 +216,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chArDone := make(chan error, 1) computeAR1 := func() { <-chWireValuesA + msmStart := time.Now() if _, err := ar.MultiExp(pk.G1.A, wireValuesA, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chArDone <- err close(chArDone) return } + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesA))) ar.AddMixed(&pk.G1.Alpha) ar.AddMixed(&deltas[0]) proof.Ar.FromJacobian(&ar) @@ -227,7 +238,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chKrs2Done := make(chan error, 1) sizeH := int(pk.Domain.Cardinality - 1) // comes from the fact the deg(H)=(n-1)+(n-1)-n=n-2 go func() { + msmStart := time.Now() _, err := krs2.MultiExp(pk.G1.Z, h[:sizeH], ecc.MultiExpConfig{NbTasks: n / 2}) + if err == nil { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", sizeH)) + } chKrs2Done <- err }() @@ -235,12 +250,16 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b // TODO Perf @Tabaie worst memory allocation offender toRemove := commitmentInfo.GetPrivateCommitted() toRemove = append(toRemove, commitmentInfo.CommitmentIndexes()) + filterStart := time.Now() _wireValues := filterHeap(wireValues[r1cs.GetNbPublicVariables():], r1cs.GetNbPublicVariables(), internal.ConcatAll(toRemove...)) + logger.Trace(log, "filter wire values", slog.Duration("took", time.Since(filterStart)), slog.Int("size", len(_wireValues))) + msmStart := time.Now() if _, err := krs.MultiExp(pk.G1.K, _wireValues, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chKrsDone <- err return } + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(_wireValues))) krs.AddMixed(&deltas[2]) n := 3 for n != 0 { @@ -283,10 +302,12 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b nbTasks *= 2 } <-chWireValuesB + msmStart := time.Now() if _, err := Bs.MultiExp(pk.G2.B, wireValuesB, ecc.MultiExpConfig{NbTasks: nbTasks}); err != nil { return err } + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB)), slog.Int("nbTasks", nbTasks)) deltaS.FromAffine(&pk.G2.Delta) deltaS.ScalarMultiplication(&deltaS, &s) Bs.AddAssign(&deltaS) diff --git a/backend/plonk/bls12-377/prove.go b/backend/plonk/bls12-377/prove.go index c34ea776f9..c087d67cf1 100644 --- a/backend/plonk/bls12-377/prove.go +++ b/backend/plonk/bls12-377/prove.go @@ -38,6 +38,7 @@ import ( cs "github.com/consensys/gnark/constraint/bls12-377" "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" ) @@ -113,6 +114,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts if err != nil { return nil, fmt.Errorf("new instance: %w", err) } + instance.log = log // solve constraints g.Go(instance.solveConstraints) @@ -197,6 +199,7 @@ type instance struct { domain0, domain1 *fft.Domain trace *Trace + log *slog.Logger } func newInstance(ctx context.Context, spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts *backend.ProverConfig) (*instance, error) { @@ -314,6 +317,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "solve constraints", slog.Duration("took", time.Since(start))) + }() solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) solverOpts = append(solverOpts, s.opt.SolverOpts...) @@ -402,6 +409,10 @@ func (s *instance) computeLagrangeOneOnCoset(cosetExpMinusOne fr.Element, index // the non-padding entries. For a 2.2M-constraint circuit on a 4M domain, // this nearly halves each MSM. func (s *instance) commitToLRO() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "commit LRO", slog.Duration("took", time.Since(start))) + }() // wait for blinding polynomials to be initialized or context to be done select { case <-s.ctx.Done(): @@ -435,9 +446,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[:offset], coeffs[:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "L"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset)) for i := 0; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -454,9 +467,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "R"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -473,9 +488,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "O"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -556,6 +573,10 @@ func (s *instance) deriveZeta() (err error) { // computeQuotient computes H func (s *instance) computeQuotient() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute quotient", slog.Duration("took", time.Since(start))) + }() s.x[id_Ql] = s.trace.Ql s.x[id_Qr] = s.trace.Qr s.x[id_Qm] = s.trace.Qm @@ -601,20 +622,26 @@ func (s *instance) computeQuotient() (err error) { s.x[id_ZS] = s.x[id_Z].ShallowClone().Shift(1) + stepStart := time.Now() numerator, err := s.computeNumerator() if err != nil { return err } + logger.Trace(s.log, "compute quotient numerator", slog.Duration("took", time.Since(stepStart)), slog.Int("domain0", int(s.domain0.Cardinality)), slog.Int("domain1", int(s.domain1.Cardinality))) + stepStart = time.Now() s.h, err = divideByZH(numerator, [2]*fft.Domain{s.domain0, s.domain1}) if err != nil { return err } + logger.Trace(s.log, "divide quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("size", s.h.Size())) // commit to h + stepStart = time.Now() if err := commitToQuotient(s.h1(), s.h2(), s.h3(), s.proof, s.pk.Kzg); err != nil { return err } + logger.Trace(s.log, "commit quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("nbParts", len(s.proof.H))) if err := s.deriveZeta(); err != nil { return err @@ -633,6 +660,10 @@ func (s *instance) computeQuotient() (err error) { } func (s *instance) buildRatioCopyConstraint() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "build ratio copy constraint", slog.Duration("took", time.Since(start))) + }() // wait for gamma and beta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -659,7 +690,9 @@ func (s *instance) buildRatioCopyConstraint() (err error) { } // commit to the blinded version of z + commitStart := time.Now() s.proof.Z, err = s.commitToPolyAndBlinding(s.x[id_Z], s.bp[id_Bz]) + logger.Trace(s.log, "commit Z", slog.Duration("took", time.Since(commitStart)), slog.Int("size", s.x[id_Z].Size())) close(s.chZ) @@ -668,6 +701,10 @@ func (s *instance) buildRatioCopyConstraint() (err error) { // open Z (blinded) at ωζ func (s *instance) openZ() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "open Z", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -724,6 +761,10 @@ func (s *instance) h3() []fr.Element { } func (s *instance) computeLinearizedPolynomial() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute linearized polynomial", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { @@ -785,7 +826,9 @@ func (s *instance) computeLinearizedPolynomial() error { ) var err error + commitStart := time.Now() s.linearizedPolynomialDigest, err = kzg.Commit(s.linearizedPolynomial, s.pk.Kzg, runtime.NumCPU()*2) + logger.Trace(s.log, "commit linearized polynomial", slog.Duration("took", time.Since(commitStart)), slog.Int("size", len(s.linearizedPolynomial))) if err != nil { return err } @@ -794,6 +837,10 @@ func (s *instance) computeLinearizedPolynomial() error { } func (s *instance) batchOpening() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "batch opening", slog.Duration("took", time.Since(start))) + }() // wait for linearizedPolynomial to be computed (or ctx.Done()) select { @@ -839,6 +886,10 @@ func (s *instance) batchOpening() error { // evaluate the full set of constraints, all polynomials in x are back in // canonical regular form at the end func (s *instance) computeNumerator() (*iop.Polynomial, error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute numerator", slog.Duration("took", time.Since(start))) + }() // init vectors that are used multiple times throughout the computation n := s.domain0.Cardinality twiddles0 := make([]fr.Element, n) @@ -994,6 +1045,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { bufBatchInvert := make([]fr.Element, s.domain0.Cardinality) for i := 0; i < rho; i++ { + iterationStart := time.Now() coset.Mul(&coset, &shifters[i]) cosetExponentiatedToNMinusOne.Exp(coset, bn). @@ -1084,6 +1136,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { cq[j].Mul(&cq[j], &cosetExponentiatedToNMinusOne) } } + logger.Trace(s.log, "compute numerator iteration", slog.Duration("took", time.Since(iterationStart)), slog.Int("iteration", i), slog.Int("rho", rho), slog.Int("size", int(n))) } // scale everything back diff --git a/backend/plonk/bls12-381/prove.go b/backend/plonk/bls12-381/prove.go index 2ca5a6cd77..e067b12c67 100644 --- a/backend/plonk/bls12-381/prove.go +++ b/backend/plonk/bls12-381/prove.go @@ -38,6 +38,7 @@ import ( cs "github.com/consensys/gnark/constraint/bls12-381" "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" ) @@ -113,6 +114,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts if err != nil { return nil, fmt.Errorf("new instance: %w", err) } + instance.log = log // solve constraints g.Go(instance.solveConstraints) @@ -197,6 +199,7 @@ type instance struct { domain0, domain1 *fft.Domain trace *Trace + log *slog.Logger } func newInstance(ctx context.Context, spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts *backend.ProverConfig) (*instance, error) { @@ -314,6 +317,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "solve constraints", slog.Duration("took", time.Since(start))) + }() solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) solverOpts = append(solverOpts, s.opt.SolverOpts...) @@ -402,6 +409,10 @@ func (s *instance) computeLagrangeOneOnCoset(cosetExpMinusOne fr.Element, index // the non-padding entries. For a 2.2M-constraint circuit on a 4M domain, // this nearly halves each MSM. func (s *instance) commitToLRO() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "commit LRO", slog.Duration("took", time.Since(start))) + }() // wait for blinding polynomials to be initialized or context to be done select { case <-s.ctx.Done(): @@ -435,9 +446,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[:offset], coeffs[:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "L"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset)) for i := 0; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -454,9 +467,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "R"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -473,9 +488,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "O"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -556,6 +573,10 @@ func (s *instance) deriveZeta() (err error) { // computeQuotient computes H func (s *instance) computeQuotient() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute quotient", slog.Duration("took", time.Since(start))) + }() s.x[id_Ql] = s.trace.Ql s.x[id_Qr] = s.trace.Qr s.x[id_Qm] = s.trace.Qm @@ -601,20 +622,26 @@ func (s *instance) computeQuotient() (err error) { s.x[id_ZS] = s.x[id_Z].ShallowClone().Shift(1) + stepStart := time.Now() numerator, err := s.computeNumerator() if err != nil { return err } + logger.Trace(s.log, "compute quotient numerator", slog.Duration("took", time.Since(stepStart)), slog.Int("domain0", int(s.domain0.Cardinality)), slog.Int("domain1", int(s.domain1.Cardinality))) + stepStart = time.Now() s.h, err = divideByZH(numerator, [2]*fft.Domain{s.domain0, s.domain1}) if err != nil { return err } + logger.Trace(s.log, "divide quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("size", s.h.Size())) // commit to h + stepStart = time.Now() if err := commitToQuotient(s.h1(), s.h2(), s.h3(), s.proof, s.pk.Kzg); err != nil { return err } + logger.Trace(s.log, "commit quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("nbParts", len(s.proof.H))) if err := s.deriveZeta(); err != nil { return err @@ -633,6 +660,10 @@ func (s *instance) computeQuotient() (err error) { } func (s *instance) buildRatioCopyConstraint() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "build ratio copy constraint", slog.Duration("took", time.Since(start))) + }() // wait for gamma and beta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -659,7 +690,9 @@ func (s *instance) buildRatioCopyConstraint() (err error) { } // commit to the blinded version of z + commitStart := time.Now() s.proof.Z, err = s.commitToPolyAndBlinding(s.x[id_Z], s.bp[id_Bz]) + logger.Trace(s.log, "commit Z", slog.Duration("took", time.Since(commitStart)), slog.Int("size", s.x[id_Z].Size())) close(s.chZ) @@ -668,6 +701,10 @@ func (s *instance) buildRatioCopyConstraint() (err error) { // open Z (blinded) at ωζ func (s *instance) openZ() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "open Z", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -724,6 +761,10 @@ func (s *instance) h3() []fr.Element { } func (s *instance) computeLinearizedPolynomial() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute linearized polynomial", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { @@ -785,7 +826,9 @@ func (s *instance) computeLinearizedPolynomial() error { ) var err error + commitStart := time.Now() s.linearizedPolynomialDigest, err = kzg.Commit(s.linearizedPolynomial, s.pk.Kzg, runtime.NumCPU()*2) + logger.Trace(s.log, "commit linearized polynomial", slog.Duration("took", time.Since(commitStart)), slog.Int("size", len(s.linearizedPolynomial))) if err != nil { return err } @@ -794,6 +837,10 @@ func (s *instance) computeLinearizedPolynomial() error { } func (s *instance) batchOpening() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "batch opening", slog.Duration("took", time.Since(start))) + }() // wait for linearizedPolynomial to be computed (or ctx.Done()) select { @@ -839,6 +886,10 @@ func (s *instance) batchOpening() error { // evaluate the full set of constraints, all polynomials in x are back in // canonical regular form at the end func (s *instance) computeNumerator() (*iop.Polynomial, error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute numerator", slog.Duration("took", time.Since(start))) + }() // init vectors that are used multiple times throughout the computation n := s.domain0.Cardinality twiddles0 := make([]fr.Element, n) @@ -994,6 +1045,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { bufBatchInvert := make([]fr.Element, s.domain0.Cardinality) for i := 0; i < rho; i++ { + iterationStart := time.Now() coset.Mul(&coset, &shifters[i]) cosetExponentiatedToNMinusOne.Exp(coset, bn). @@ -1084,6 +1136,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { cq[j].Mul(&cq[j], &cosetExponentiatedToNMinusOne) } } + logger.Trace(s.log, "compute numerator iteration", slog.Duration("took", time.Since(iterationStart)), slog.Int("iteration", i), slog.Int("rho", rho), slog.Int("size", int(n))) } // scale everything back diff --git a/backend/plonk/bn254/prove.go b/backend/plonk/bn254/prove.go index fca5f43949..d91fdbce82 100644 --- a/backend/plonk/bn254/prove.go +++ b/backend/plonk/bn254/prove.go @@ -38,6 +38,7 @@ import ( cs "github.com/consensys/gnark/constraint/bn254" "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" ) @@ -113,6 +114,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts if err != nil { return nil, fmt.Errorf("new instance: %w", err) } + instance.log = log // solve constraints g.Go(instance.solveConstraints) @@ -197,6 +199,7 @@ type instance struct { domain0, domain1 *fft.Domain trace *Trace + log *slog.Logger } func newInstance(ctx context.Context, spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts *backend.ProverConfig) (*instance, error) { @@ -314,6 +317,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "solve constraints", slog.Duration("took", time.Since(start))) + }() solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) solverOpts = append(solverOpts, s.opt.SolverOpts...) @@ -402,6 +409,10 @@ func (s *instance) computeLagrangeOneOnCoset(cosetExpMinusOne fr.Element, index // the non-padding entries. For a 2.2M-constraint circuit on a 4M domain, // this nearly halves each MSM. func (s *instance) commitToLRO() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "commit LRO", slog.Duration("took", time.Since(start))) + }() // wait for blinding polynomials to be initialized or context to be done select { case <-s.ctx.Done(): @@ -435,9 +446,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[:offset], coeffs[:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "L"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset)) for i := 0; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -454,9 +467,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "R"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -473,9 +488,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "O"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -556,6 +573,10 @@ func (s *instance) deriveZeta() (err error) { // computeQuotient computes H func (s *instance) computeQuotient() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute quotient", slog.Duration("took", time.Since(start))) + }() s.x[id_Ql] = s.trace.Ql s.x[id_Qr] = s.trace.Qr s.x[id_Qm] = s.trace.Qm @@ -601,20 +622,26 @@ func (s *instance) computeQuotient() (err error) { s.x[id_ZS] = s.x[id_Z].ShallowClone().Shift(1) + stepStart := time.Now() numerator, err := s.computeNumerator() if err != nil { return err } + logger.Trace(s.log, "compute quotient numerator", slog.Duration("took", time.Since(stepStart)), slog.Int("domain0", int(s.domain0.Cardinality)), slog.Int("domain1", int(s.domain1.Cardinality))) + stepStart = time.Now() s.h, err = divideByZH(numerator, [2]*fft.Domain{s.domain0, s.domain1}) if err != nil { return err } + logger.Trace(s.log, "divide quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("size", s.h.Size())) // commit to h + stepStart = time.Now() if err := commitToQuotient(s.h1(), s.h2(), s.h3(), s.proof, s.pk.Kzg); err != nil { return err } + logger.Trace(s.log, "commit quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("nbParts", len(s.proof.H))) if err := s.deriveZeta(); err != nil { return err @@ -633,6 +660,10 @@ func (s *instance) computeQuotient() (err error) { } func (s *instance) buildRatioCopyConstraint() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "build ratio copy constraint", slog.Duration("took", time.Since(start))) + }() // wait for gamma and beta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -659,7 +690,9 @@ func (s *instance) buildRatioCopyConstraint() (err error) { } // commit to the blinded version of z + commitStart := time.Now() s.proof.Z, err = s.commitToPolyAndBlinding(s.x[id_Z], s.bp[id_Bz]) + logger.Trace(s.log, "commit Z", slog.Duration("took", time.Since(commitStart)), slog.Int("size", s.x[id_Z].Size())) close(s.chZ) @@ -668,6 +701,10 @@ func (s *instance) buildRatioCopyConstraint() (err error) { // open Z (blinded) at ωζ func (s *instance) openZ() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "open Z", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -724,6 +761,10 @@ func (s *instance) h3() []fr.Element { } func (s *instance) computeLinearizedPolynomial() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute linearized polynomial", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { @@ -785,7 +826,9 @@ func (s *instance) computeLinearizedPolynomial() error { ) var err error + commitStart := time.Now() s.linearizedPolynomialDigest, err = kzg.Commit(s.linearizedPolynomial, s.pk.Kzg, runtime.NumCPU()*2) + logger.Trace(s.log, "commit linearized polynomial", slog.Duration("took", time.Since(commitStart)), slog.Int("size", len(s.linearizedPolynomial))) if err != nil { return err } @@ -794,6 +837,10 @@ func (s *instance) computeLinearizedPolynomial() error { } func (s *instance) batchOpening() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "batch opening", slog.Duration("took", time.Since(start))) + }() // wait for linearizedPolynomial to be computed (or ctx.Done()) select { @@ -839,6 +886,10 @@ func (s *instance) batchOpening() error { // evaluate the full set of constraints, all polynomials in x are back in // canonical regular form at the end func (s *instance) computeNumerator() (*iop.Polynomial, error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute numerator", slog.Duration("took", time.Since(start))) + }() // init vectors that are used multiple times throughout the computation n := s.domain0.Cardinality twiddles0 := make([]fr.Element, n) @@ -994,6 +1045,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { bufBatchInvert := make([]fr.Element, s.domain0.Cardinality) for i := 0; i < rho; i++ { + iterationStart := time.Now() coset.Mul(&coset, &shifters[i]) cosetExponentiatedToNMinusOne.Exp(coset, bn). @@ -1084,6 +1136,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { cq[j].Mul(&cq[j], &cosetExponentiatedToNMinusOne) } } + logger.Trace(s.log, "compute numerator iteration", slog.Duration("took", time.Since(iterationStart)), slog.Int("iteration", i), slog.Int("rho", rho), slog.Int("size", int(n))) } // scale everything back diff --git a/backend/plonk/bw6-761/prove.go b/backend/plonk/bw6-761/prove.go index 063db7a26c..b4c98f4944 100644 --- a/backend/plonk/bw6-761/prove.go +++ b/backend/plonk/bw6-761/prove.go @@ -38,6 +38,7 @@ import ( cs "github.com/consensys/gnark/constraint/bw6-761" "github.com/consensys/gnark/constraint/solver" fcs "github.com/consensys/gnark/frontend/cs" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" ) @@ -113,6 +114,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts if err != nil { return nil, fmt.Errorf("new instance: %w", err) } + instance.log = log // solve constraints g.Go(instance.solveConstraints) @@ -197,6 +199,7 @@ type instance struct { domain0, domain1 *fft.Domain trace *Trace + log *slog.Logger } func newInstance(ctx context.Context, spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts *backend.ProverConfig) (*instance, error) { @@ -314,6 +317,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "solve constraints", slog.Duration("took", time.Since(start))) + }() solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) solverOpts = append(solverOpts, s.opt.SolverOpts...) @@ -402,6 +409,10 @@ func (s *instance) computeLagrangeOneOnCoset(cosetExpMinusOne fr.Element, index // the non-padding entries. For a 2.2M-constraint circuit on a 4M domain, // this nearly halves each MSM. func (s *instance) commitToLRO() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "commit LRO", slog.Duration("took", time.Since(start))) + }() // wait for blinding polynomials to be initialized or context to be done select { case <-s.ctx.Done(): @@ -435,9 +446,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[:offset], coeffs[:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "L"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset)) for i := 0; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -454,9 +467,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "R"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -473,9 +488,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "O"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -556,6 +573,10 @@ func (s *instance) deriveZeta() (err error) { // computeQuotient computes H func (s *instance) computeQuotient() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute quotient", slog.Duration("took", time.Since(start))) + }() s.x[id_Ql] = s.trace.Ql s.x[id_Qr] = s.trace.Qr s.x[id_Qm] = s.trace.Qm @@ -601,20 +622,26 @@ func (s *instance) computeQuotient() (err error) { s.x[id_ZS] = s.x[id_Z].ShallowClone().Shift(1) + stepStart := time.Now() numerator, err := s.computeNumerator() if err != nil { return err } + logger.Trace(s.log, "compute quotient numerator", slog.Duration("took", time.Since(stepStart)), slog.Int("domain0", int(s.domain0.Cardinality)), slog.Int("domain1", int(s.domain1.Cardinality))) + stepStart = time.Now() s.h, err = divideByZH(numerator, [2]*fft.Domain{s.domain0, s.domain1}) if err != nil { return err } + logger.Trace(s.log, "divide quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("size", s.h.Size())) // commit to h + stepStart = time.Now() if err := commitToQuotient(s.h1(), s.h2(), s.h3(), s.proof, s.pk.Kzg); err != nil { return err } + logger.Trace(s.log, "commit quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("nbParts", len(s.proof.H))) if err := s.deriveZeta(); err != nil { return err @@ -633,6 +660,10 @@ func (s *instance) computeQuotient() (err error) { } func (s *instance) buildRatioCopyConstraint() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "build ratio copy constraint", slog.Duration("took", time.Since(start))) + }() // wait for gamma and beta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -659,7 +690,9 @@ func (s *instance) buildRatioCopyConstraint() (err error) { } // commit to the blinded version of z + commitStart := time.Now() s.proof.Z, err = s.commitToPolyAndBlinding(s.x[id_Z], s.bp[id_Bz]) + logger.Trace(s.log, "commit Z", slog.Duration("took", time.Since(commitStart)), slog.Int("size", s.x[id_Z].Size())) close(s.chZ) @@ -668,6 +701,10 @@ func (s *instance) buildRatioCopyConstraint() (err error) { // open Z (blinded) at ωζ func (s *instance) openZ() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "open Z", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -724,6 +761,10 @@ func (s *instance) h3() []fr.Element { } func (s *instance) computeLinearizedPolynomial() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute linearized polynomial", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { @@ -785,7 +826,9 @@ func (s *instance) computeLinearizedPolynomial() error { ) var err error + commitStart := time.Now() s.linearizedPolynomialDigest, err = kzg.Commit(s.linearizedPolynomial, s.pk.Kzg, runtime.NumCPU()*2) + logger.Trace(s.log, "commit linearized polynomial", slog.Duration("took", time.Since(commitStart)), slog.Int("size", len(s.linearizedPolynomial))) if err != nil { return err } @@ -794,6 +837,10 @@ func (s *instance) computeLinearizedPolynomial() error { } func (s *instance) batchOpening() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "batch opening", slog.Duration("took", time.Since(start))) + }() // wait for linearizedPolynomial to be computed (or ctx.Done()) select { @@ -839,6 +886,10 @@ func (s *instance) batchOpening() error { // evaluate the full set of constraints, all polynomials in x are back in // canonical regular form at the end func (s *instance) computeNumerator() (*iop.Polynomial, error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute numerator", slog.Duration("took", time.Since(start))) + }() // init vectors that are used multiple times throughout the computation n := s.domain0.Cardinality twiddles0 := make([]fr.Element, n) @@ -994,6 +1045,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { bufBatchInvert := make([]fr.Element, s.domain0.Cardinality) for i := 0; i < rho; i++ { + iterationStart := time.Now() coset.Mul(&coset, &shifters[i]) cosetExponentiatedToNMinusOne.Exp(coset, bn). @@ -1084,6 +1136,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { cq[j].Mul(&cq[j], &cosetExponentiatedToNMinusOne) } } + logger.Trace(s.log, "compute numerator iteration", slog.Duration("took", time.Since(iterationStart)), slog.Int("iteration", i), slog.Int("rho", rho), slog.Int("size", int(n))) } // scale everything back diff --git a/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl index 9e7f45e444..e24cf171b7 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl @@ -11,6 +11,7 @@ import ( {{- template "import_hash_to_field" . }} "github.com/consensys/gnark/constraint" "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" "log/slog" @@ -95,15 +96,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil })) + solveStart := time.Now() _solution, err := r1cs.Solve(fullWitness, solverOpts...) if err != nil { return nil, err } + logger.Trace(log, "solving done", slog.Duration("took", time.Since(solveStart))) solution := _solution.(*cs.R1CSSolution) wireValues := []fr.Element(solution.W) start := time.Now() + commitmentStart := time.Now() poks := make([]curve.G1Affine, len(pk.CommitmentKeys)) for i := range pk.CommitmentKeys { @@ -124,12 +128,15 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b if _, err = proof.CommitmentPok.Fold(poks, challenge[0], ecc.MultiExpConfig{NbTasks: 1}); err != nil { return nil, err } + logger.Trace(log, "commitment proof of knowledge", slog.Duration("took", time.Since(commitmentStart)), slog.Int("nbCommitments", len(pk.CommitmentKeys))) // H (witness reduction / FFT part) var h []fr.Element chHDone := make(chan struct{}, 1) go func() { + hStart := time.Now() h = computeH(solution.A, solution.B, solution.C, &pk.Domain) + logger.Trace(log, "computeH", slog.Duration("took", time.Since(hStart)), slog.Int("size", len(h))) solution.A = nil solution.B = nil solution.C = nil @@ -188,11 +195,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chBs1Done := make(chan error, 1) computeBS1 := func() { <-chWireValuesB + msmStart := time.Now() if _, err := bs1.MultiExp(pk.G1.B, wireValuesB, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chBs1Done <- err close(chBs1Done) return } + logger.Trace(log, "MSM Bs1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB))) bs1.AddMixed(&pk.G1.Beta) bs1.AddMixed(&deltas[1]) chBs1Done <- nil @@ -201,11 +210,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chArDone := make(chan error, 1) computeAR1 := func() { <-chWireValuesA + msmStart := time.Now() if _, err := ar.MultiExp(pk.G1.A, wireValuesA, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chArDone <- err close(chArDone) return } + logger.Trace(log, "MSM Ar1", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesA))) ar.AddMixed(&pk.G1.Alpha) ar.AddMixed(&deltas[0]) proof.Ar.FromJacobian(&ar) @@ -221,7 +232,11 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b chKrs2Done := make(chan error, 1) sizeH := int(pk.Domain.Cardinality - 1) // comes from the fact the deg(H)=(n-1)+(n-1)-n=n-2 go func() { + msmStart := time.Now() _, err := krs2.MultiExp(pk.G1.Z, h[:sizeH], ecc.MultiExpConfig{NbTasks: n / 2}) + if err == nil { + logger.Trace(log, "MSM Krs2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", sizeH)) + } chKrs2Done <- err }() @@ -229,12 +244,16 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b // TODO Perf @Tabaie worst memory allocation offender toRemove := commitmentInfo.GetPrivateCommitted() toRemove = append(toRemove, commitmentInfo.CommitmentIndexes()) + filterStart := time.Now() _wireValues := filterHeap(wireValues[r1cs.GetNbPublicVariables():], r1cs.GetNbPublicVariables(), internal.ConcatAll(toRemove...)) + logger.Trace(log, "filter wire values", slog.Duration("took", time.Since(filterStart)), slog.Int("size", len(_wireValues))) + msmStart := time.Now() if _, err := krs.MultiExp(pk.G1.K, _wireValues, ecc.MultiExpConfig{NbTasks: n / 2}); err != nil { chKrsDone <- err return } + logger.Trace(log, "MSM Krs", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(_wireValues))) krs.AddMixed(&deltas[2]) n := 3 for n != 0 { @@ -277,10 +296,12 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b nbTasks *= 2 } <-chWireValuesB + msmStart := time.Now() if _, err := Bs.MultiExp(pk.G2.B, wireValuesB, ecc.MultiExpConfig{NbTasks: nbTasks}); err != nil { return err } + logger.Trace(log, "MSM Bs2 G2", slog.Duration("took", time.Since(msmStart)), slog.Int("size", len(wireValuesB)), slog.Int("nbTasks", nbTasks)) deltaS.FromAffine(&pk.G2.Delta) deltaS.ScalarMultiplication(&deltaS, &s) Bs.AddAssign(&deltaS) diff --git a/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl b/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl index f5d8764061..786c044eb0 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl @@ -25,6 +25,7 @@ import ( {{ template "import_backend_cs" . }} "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/constraint/solver" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" fcs "github.com/consensys/gnark/frontend/cs" ) @@ -102,6 +103,7 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts if err != nil { return nil, fmt.Errorf("new instance: %w", err) } + instance.log = log // solve constraints g.Go(instance.solveConstraints) @@ -186,6 +188,7 @@ type instance struct { domain0, domain1 *fft.Domain trace *Trace + log *slog.Logger } func newInstance(ctx context.Context, spr *cs.SparseR1CS, pk *ProvingKey, fullWitness witness.Witness, opts *backend.ProverConfig) (*instance, error) { @@ -303,6 +306,10 @@ func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { // solveConstraints computes the evaluation of the polynomials L, R, O // and sets x[id_L], x[id_R], x[id_O] in Lagrange form func (s *instance) solveConstraints() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "solve constraints", slog.Duration("took", time.Since(start))) + }() solverOpts := make([]solver.Option, 0, len(s.opt.SolverOpts)+1) solverOpts = append(solverOpts, solver.WithLogger(s.opt.Logger)) solverOpts = append(solverOpts, s.opt.SolverOpts...) @@ -391,6 +398,10 @@ func (s *instance) computeLagrangeOneOnCoset(cosetExpMinusOne fr.Element, index // the non-padding entries. For a 2.2M-constraint circuit on a 4M domain, // this nearly halves each MSM. func (s *instance) commitToLRO() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "commit LRO", slog.Duration("took", time.Since(start))) + }() // wait for blinding polynomials to be initialized or context to be done select { case <-s.ctx.Done(): @@ -424,9 +435,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[:offset], coeffs[:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "L"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset)) for i := 0; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -443,9 +456,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "R"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -462,9 +477,11 @@ func (s *instance) commitToLRO() error { coeffs[i].Sub(&coeffs[i], &s0) } var commit curve.G1Affine + msmStart := time.Now() if _, err = commit.MultiExp(s.pk.KzgLagrange.G1[nbPublic:offset], coeffs[nbPublic:offset], ecc.MultiExpConfig{}); err != nil { return } + logger.Trace(s.log, "MSM LRO", slog.String("poly", "O"), slog.Duration("took", time.Since(msmStart)), slog.Int("size", offset-nbPublic)) for i := nbPublic; i < offset; i++ { coeffs[i].Add(&coeffs[i], &s0) } @@ -545,6 +562,10 @@ func (s *instance) deriveZeta() (err error) { // computeQuotient computes H func (s *instance) computeQuotient() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute quotient", slog.Duration("took", time.Since(start))) + }() s.x[id_Ql] = s.trace.Ql s.x[id_Qr] = s.trace.Qr s.x[id_Qm] = s.trace.Qm @@ -590,20 +611,26 @@ func (s *instance) computeQuotient() (err error) { s.x[id_ZS] = s.x[id_Z].ShallowClone().Shift(1) + stepStart := time.Now() numerator, err := s.computeNumerator() if err != nil { return err } + logger.Trace(s.log, "compute quotient numerator", slog.Duration("took", time.Since(stepStart)), slog.Int("domain0", int(s.domain0.Cardinality)), slog.Int("domain1", int(s.domain1.Cardinality))) + stepStart = time.Now() s.h, err = divideByZH(numerator, [2]*fft.Domain{s.domain0, s.domain1}) if err != nil { return err } + logger.Trace(s.log, "divide quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("size", s.h.Size())) // commit to h + stepStart = time.Now() if err := commitToQuotient(s.h1(), s.h2(), s.h3(), s.proof, s.pk.Kzg); err != nil { return err } + logger.Trace(s.log, "commit quotient", slog.Duration("took", time.Since(stepStart)), slog.Int("nbParts", len(s.proof.H))) if err := s.deriveZeta(); err != nil { return err @@ -622,6 +649,10 @@ func (s *instance) computeQuotient() (err error) { } func (s *instance) buildRatioCopyConstraint() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "build ratio copy constraint", slog.Duration("took", time.Since(start))) + }() // wait for gamma and beta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -648,7 +679,9 @@ func (s *instance) buildRatioCopyConstraint() (err error) { } // commit to the blinded version of z + commitStart := time.Now() s.proof.Z, err = s.commitToPolyAndBlinding(s.x[id_Z], s.bp[id_Bz]) + logger.Trace(s.log, "commit Z", slog.Duration("took", time.Since(commitStart)), slog.Int("size", s.x[id_Z].Size())) close(s.chZ) @@ -657,6 +690,10 @@ func (s *instance) buildRatioCopyConstraint() (err error) { // open Z (blinded) at ωζ func (s *instance) openZ() (err error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "open Z", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { case <-s.ctx.Done(): @@ -713,6 +750,10 @@ func (s *instance) h3() []fr.Element { } func (s *instance) computeLinearizedPolynomial() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute linearized polynomial", slog.Duration("took", time.Since(start))) + }() // wait for H to be committed and zeta to be derived (or ctx.Done()) select { @@ -774,7 +815,9 @@ func (s *instance) computeLinearizedPolynomial() error { ) var err error + commitStart := time.Now() s.linearizedPolynomialDigest, err = kzg.Commit(s.linearizedPolynomial, s.pk.Kzg, runtime.NumCPU()*2) + logger.Trace(s.log, "commit linearized polynomial", slog.Duration("took", time.Since(commitStart)), slog.Int("size", len(s.linearizedPolynomial))) if err != nil { return err } @@ -783,6 +826,10 @@ func (s *instance) computeLinearizedPolynomial() error { } func (s *instance) batchOpening() error { + start := time.Now() + defer func() { + logger.Trace(s.log, "batch opening", slog.Duration("took", time.Since(start))) + }() // wait for linearizedPolynomial to be computed (or ctx.Done()) select { @@ -828,6 +875,10 @@ func (s *instance) batchOpening() error { // evaluate the full set of constraints, all polynomials in x are back in // canonical regular form at the end func (s *instance) computeNumerator() (*iop.Polynomial, error) { + start := time.Now() + defer func() { + logger.Trace(s.log, "compute numerator", slog.Duration("took", time.Since(start))) + }() // init vectors that are used multiple times throughout the computation n := s.domain0.Cardinality twiddles0 := make([]fr.Element, n) @@ -983,6 +1034,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { bufBatchInvert := make([]fr.Element, s.domain0.Cardinality) for i := 0; i < rho; i++ { + iterationStart := time.Now() coset.Mul(&coset, &shifters[i]) cosetExponentiatedToNMinusOne.Exp(coset, bn). @@ -1073,6 +1125,7 @@ func (s *instance) computeNumerator() (*iop.Polynomial, error) { cq[j].Mul(&cq[j], &cosetExponentiatedToNMinusOne) } } + logger.Trace(s.log, "compute numerator iteration", slog.Duration("took", time.Since(iterationStart)), slog.Int("iteration", i), slog.Int("rho", rho), slog.Int("size", int(n))) } // scale everything back From 1b71a18de4315a08e8861ab6806cb5d3e40ddcb1 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 23:12:20 +0000 Subject: [PATCH 39/44] feat: add logs for serialization steps --- backend/groth16/bls12-377/marshal.go | 72 +++++++++++++----- backend/groth16/bls12-381/marshal.go | 72 +++++++++++++----- backend/groth16/bn254/marshal.go | 72 +++++++++++++----- backend/groth16/bw6-761/marshal.go | 72 +++++++++++++----- .../groth16/groth16.marshal.go.tmpl | 74 ++++++++++++++----- 5 files changed, 276 insertions(+), 86 deletions(-) diff --git a/backend/groth16/bls12-377/marshal.go b/backend/groth16/bls12-377/marshal.go index 017a3aa689..9d5730d469 100644 --- a/backend/groth16/bls12-377/marshal.go +++ b/backend/groth16/bls12-377/marshal.go @@ -10,12 +10,21 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" + "context" "fmt" "io" + "log/slog" + "time" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo writes binary encoding of the Proof elements to writer // points are stored in compressed form Ar | Krs | Bs // use WriteRawTo(...) to encode the proof without point compression @@ -30,7 +39,12 @@ func (proof *Proof) WriteRawTo(w io.Writer) (n int64, err error) { return proof.writeTo(w, true) } -func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -60,6 +74,10 @@ func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { // ReadFrom attempts to decode a Proof from reader // Proof must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() dec := curve.NewDecoder(r) @@ -100,7 +118,12 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (n int64, err error) { // follows bellman format: // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 -func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { +func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -128,7 +151,7 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { return enc.BytesWritten(), err } } - var n int64 + var commitmentKeysBytes int64 for i := range vk.CommitmentKeys { var ( m int64 @@ -139,12 +162,12 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { } else { m, err = vk.CommitmentKeys[i].WriteTo(w) } - n += m + commitmentKeysBytes += m if err != nil { - return n + enc.BytesWritten(), err + return commitmentKeysBytes + enc.BytesWritten(), err } } - return n + enc.BytesWritten(), nil + return commitmentKeysBytes + enc.BytesWritten(), nil } // ReadFrom attempts to decode a VerifyingKey from reader @@ -162,7 +185,12 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return vk.readFrom(r, true) } -func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { +func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key"), slog.Bool("subgroup_checks", !raw)) + }() + var dec *curve.Decoder if raw { dec = curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -195,7 +223,7 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - var n int64 + var commitmentKeysBytes int64 for i := 0; i < int(nbCommitments); i++ { var ( m int64 @@ -207,22 +235,22 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { } else { m, err = commitmentKey.ReadFrom(r) } - n += m + commitmentKeysBytes += m if err != nil { - return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) } if len(vk.CommitmentKeys) != int(nbCommitments) { - return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } - return n + dec.BytesRead(), nil + return commitmentKeysBytes + dec.BytesRead(), nil } // WriteTo writes binary encoding of the key elements to writer @@ -239,8 +267,13 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { return pk.writeTo(w, true) } -func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (int64, error) { - n, err := pk.Domain.WriteTo(w) +func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", raw)) + }() + + n, err = pk.Domain.WriteTo(w) if err != nil { return n, err } @@ -312,8 +345,13 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, curve.NoSubgroupChecks()) } -func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { - n, err := pk.Domain.ReadFrom(r) +func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", len(decOptions) == 0)) + }() + + n, err = pk.Domain.ReadFrom(r) if err != nil { return n, fmt.Errorf("read domain: %w", err) } diff --git a/backend/groth16/bls12-381/marshal.go b/backend/groth16/bls12-381/marshal.go index f91a198317..a28c025de3 100644 --- a/backend/groth16/bls12-381/marshal.go +++ b/backend/groth16/bls12-381/marshal.go @@ -10,12 +10,21 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" + "context" "fmt" "io" + "log/slog" + "time" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo writes binary encoding of the Proof elements to writer // points are stored in compressed form Ar | Krs | Bs // use WriteRawTo(...) to encode the proof without point compression @@ -30,7 +39,12 @@ func (proof *Proof) WriteRawTo(w io.Writer) (n int64, err error) { return proof.writeTo(w, true) } -func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -60,6 +74,10 @@ func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { // ReadFrom attempts to decode a Proof from reader // Proof must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() dec := curve.NewDecoder(r) @@ -100,7 +118,12 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (n int64, err error) { // follows bellman format: // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 -func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { +func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -128,7 +151,7 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { return enc.BytesWritten(), err } } - var n int64 + var commitmentKeysBytes int64 for i := range vk.CommitmentKeys { var ( m int64 @@ -139,12 +162,12 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { } else { m, err = vk.CommitmentKeys[i].WriteTo(w) } - n += m + commitmentKeysBytes += m if err != nil { - return n + enc.BytesWritten(), err + return commitmentKeysBytes + enc.BytesWritten(), err } } - return n + enc.BytesWritten(), nil + return commitmentKeysBytes + enc.BytesWritten(), nil } // ReadFrom attempts to decode a VerifyingKey from reader @@ -162,7 +185,12 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return vk.readFrom(r, true) } -func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { +func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key"), slog.Bool("subgroup_checks", !raw)) + }() + var dec *curve.Decoder if raw { dec = curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -195,7 +223,7 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - var n int64 + var commitmentKeysBytes int64 for i := 0; i < int(nbCommitments); i++ { var ( m int64 @@ -207,22 +235,22 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { } else { m, err = commitmentKey.ReadFrom(r) } - n += m + commitmentKeysBytes += m if err != nil { - return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) } if len(vk.CommitmentKeys) != int(nbCommitments) { - return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } - return n + dec.BytesRead(), nil + return commitmentKeysBytes + dec.BytesRead(), nil } // WriteTo writes binary encoding of the key elements to writer @@ -239,8 +267,13 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { return pk.writeTo(w, true) } -func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (int64, error) { - n, err := pk.Domain.WriteTo(w) +func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", raw)) + }() + + n, err = pk.Domain.WriteTo(w) if err != nil { return n, err } @@ -312,8 +345,13 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, curve.NoSubgroupChecks()) } -func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { - n, err := pk.Domain.ReadFrom(r) +func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", len(decOptions) == 0)) + }() + + n, err = pk.Domain.ReadFrom(r) if err != nil { return n, fmt.Errorf("read domain: %w", err) } diff --git a/backend/groth16/bn254/marshal.go b/backend/groth16/bn254/marshal.go index 2f59b04662..081e7fe8f3 100644 --- a/backend/groth16/bn254/marshal.go +++ b/backend/groth16/bn254/marshal.go @@ -10,12 +10,21 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" + "context" "fmt" "io" + "log/slog" + "time" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo writes binary encoding of the Proof elements to writer // points are stored in compressed form Ar | Krs | Bs // use WriteRawTo(...) to encode the proof without point compression @@ -30,7 +39,12 @@ func (proof *Proof) WriteRawTo(w io.Writer) (n int64, err error) { return proof.writeTo(w, true) } -func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -60,6 +74,10 @@ func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { // ReadFrom attempts to decode a Proof from reader // Proof must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() dec := curve.NewDecoder(r) @@ -100,7 +118,12 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (n int64, err error) { // follows bellman format: // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 -func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { +func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -128,7 +151,7 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { return enc.BytesWritten(), err } } - var n int64 + var commitmentKeysBytes int64 for i := range vk.CommitmentKeys { var ( m int64 @@ -139,12 +162,12 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { } else { m, err = vk.CommitmentKeys[i].WriteTo(w) } - n += m + commitmentKeysBytes += m if err != nil { - return n + enc.BytesWritten(), err + return commitmentKeysBytes + enc.BytesWritten(), err } } - return n + enc.BytesWritten(), nil + return commitmentKeysBytes + enc.BytesWritten(), nil } // ReadFrom attempts to decode a VerifyingKey from reader @@ -162,7 +185,12 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return vk.readFrom(r, true) } -func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { +func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key"), slog.Bool("subgroup_checks", !raw)) + }() + var dec *curve.Decoder if raw { dec = curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -195,7 +223,7 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - var n int64 + var commitmentKeysBytes int64 for i := 0; i < int(nbCommitments); i++ { var ( m int64 @@ -207,22 +235,22 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { } else { m, err = commitmentKey.ReadFrom(r) } - n += m + commitmentKeysBytes += m if err != nil { - return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) } if len(vk.CommitmentKeys) != int(nbCommitments) { - return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } - return n + dec.BytesRead(), nil + return commitmentKeysBytes + dec.BytesRead(), nil } // WriteTo writes binary encoding of the key elements to writer @@ -239,8 +267,13 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { return pk.writeTo(w, true) } -func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (int64, error) { - n, err := pk.Domain.WriteTo(w) +func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", raw)) + }() + + n, err = pk.Domain.WriteTo(w) if err != nil { return n, err } @@ -312,8 +345,13 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, curve.NoSubgroupChecks()) } -func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { - n, err := pk.Domain.ReadFrom(r) +func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", len(decOptions) == 0)) + }() + + n, err = pk.Domain.ReadFrom(r) if err != nil { return n, fmt.Errorf("read domain: %w", err) } diff --git a/backend/groth16/bw6-761/marshal.go b/backend/groth16/bw6-761/marshal.go index ab657ba88a..b5687d2c53 100644 --- a/backend/groth16/bw6-761/marshal.go +++ b/backend/groth16/bw6-761/marshal.go @@ -10,12 +10,21 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" + "context" "fmt" "io" + "log/slog" + "time" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo writes binary encoding of the Proof elements to writer // points are stored in compressed form Ar | Krs | Bs // use WriteRawTo(...) to encode the proof without point compression @@ -30,7 +39,12 @@ func (proof *Proof) WriteRawTo(w io.Writer) (n int64, err error) { return proof.writeTo(w, true) } -func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -60,6 +74,10 @@ func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { // ReadFrom attempts to decode a Proof from reader // Proof must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() dec := curve.NewDecoder(r) @@ -100,7 +118,12 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (n int64, err error) { // follows bellman format: // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 -func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { +func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -128,7 +151,7 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { return enc.BytesWritten(), err } } - var n int64 + var commitmentKeysBytes int64 for i := range vk.CommitmentKeys { var ( m int64 @@ -139,12 +162,12 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { } else { m, err = vk.CommitmentKeys[i].WriteTo(w) } - n += m + commitmentKeysBytes += m if err != nil { - return n + enc.BytesWritten(), err + return commitmentKeysBytes + enc.BytesWritten(), err } } - return n + enc.BytesWritten(), nil + return commitmentKeysBytes + enc.BytesWritten(), nil } // ReadFrom attempts to decode a VerifyingKey from reader @@ -162,7 +185,12 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return vk.readFrom(r, true) } -func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { +func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key"), slog.Bool("subgroup_checks", !raw)) + }() + var dec *curve.Decoder if raw { dec = curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -195,7 +223,7 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - var n int64 + var commitmentKeysBytes int64 for i := 0; i < int(nbCommitments); i++ { var ( m int64 @@ -207,22 +235,22 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { } else { m, err = commitmentKey.ReadFrom(r) } - n += m + commitmentKeysBytes += m if err != nil { - return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) } if len(vk.CommitmentKeys) != int(nbCommitments) { - return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } - return n + dec.BytesRead(), nil + return commitmentKeysBytes + dec.BytesRead(), nil } // WriteTo writes binary encoding of the key elements to writer @@ -239,8 +267,13 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { return pk.writeTo(w, true) } -func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (int64, error) { - n, err := pk.Domain.WriteTo(w) +func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", raw)) + }() + + n, err = pk.Domain.WriteTo(w) if err != nil { return n, err } @@ -312,8 +345,13 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, curve.NoSubgroupChecks()) } -func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { - n, err := pk.Domain.ReadFrom(r) +func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", len(decOptions) == 0)) + }() + + n, err = pk.Domain.ReadFrom(r) if err != nil { return n, fmt.Errorf("read domain: %w", err) } diff --git a/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl index 4a839d36b1..f04c5b651a 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl @@ -1,13 +1,22 @@ import ( {{ template "import_curve" . }} {{ template "import_pedersen" . }} + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark-crypto/utils/unsafe" + "context" "fmt" "io" + "log/slog" + "time" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo writes binary encoding of the Proof elements to writer // points are stored in compressed form Ar | Krs | Bs // use WriteRawTo(...) to encode the proof without point compression @@ -22,7 +31,12 @@ func (proof *Proof) WriteRawTo(w io.Writer) (n int64, err error) { return proof.writeTo(w, true) } -func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -53,6 +67,10 @@ func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { // ReadFrom attempts to decode a Proof from reader // Proof must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() dec := curve.NewDecoder(r) @@ -93,7 +111,12 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (n int64, err error) { // follows bellman format: // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 -func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { +func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", raw)) + }() + var enc *curve.Encoder if raw { enc = curve.NewEncoder(w, curve.RawEncoding()) @@ -121,7 +144,7 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { return enc.BytesWritten(), err } } - var n int64 + var commitmentKeysBytes int64 for i := range vk.CommitmentKeys { var ( m int64 @@ -132,12 +155,12 @@ func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { } else { m, err = vk.CommitmentKeys[i].WriteTo(w) } - n += m + commitmentKeysBytes += m if err != nil { - return n + enc.BytesWritten(), err + return commitmentKeysBytes + enc.BytesWritten(), err } } - return n + enc.BytesWritten(), nil + return commitmentKeysBytes + enc.BytesWritten(), nil } // ReadFrom attempts to decode a VerifyingKey from reader @@ -155,7 +178,12 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return vk.readFrom(r, true) } -func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { +func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key"), slog.Bool("subgroup_checks", !raw)) + }() + var dec *curve.Decoder if raw { dec = curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -188,7 +216,7 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - var n int64 + var commitmentKeysBytes int64 for i := 0; i < int(nbCommitments); i++ { var ( m int64 @@ -200,22 +228,22 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { } else { m, err = commitmentKey.ReadFrom(r) } - n += m + commitmentKeysBytes += m if err != nil { - return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) } if len(vk.CommitmentKeys) != int(nbCommitments) { - return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) + return commitmentKeysBytes + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } - return n + dec.BytesRead(), nil + return commitmentKeysBytes + dec.BytesRead(), nil } @@ -235,8 +263,13 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { return pk.writeTo(w, true) } -func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (int64, error) { - n, err := pk.Domain.WriteTo(w) +func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", raw)) + }() + + n, err = pk.Domain.WriteTo(w) if err != nil { return n, err } @@ -309,8 +342,13 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, curve.NoSubgroupChecks()) } -func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { - n, err := pk.Domain.ReadFrom(r) +func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", len(decOptions) == 0)) + }() + + n, err = pk.Domain.ReadFrom(r) if err != nil { return n, fmt.Errorf("read domain: %w", err) } @@ -534,4 +572,4 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { return nil -} \ No newline at end of file +} From 7200b2e80f7bfe7f88bd0faa93a9e4b8e7991a85 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 23:14:37 +0000 Subject: [PATCH 40/44] feat: log constraint system serialization --- constraint/babybear/marshal.go | 30 ++++++++++++----- constraint/bls12-377/marshal.go | 30 ++++++++++++----- constraint/bls12-381/marshal.go | 30 ++++++++++++----- constraint/bn254/marshal.go | 30 ++++++++++++----- constraint/bw6-761/marshal.go | 30 ++++++++++++----- constraint/grumpkin/marshal.go | 30 ++++++++++++----- constraint/koalabear/marshal.go | 30 ++++++++++++----- constraint/tinyfield/marshal.go | 30 ++++++++++++----- .../template/representations/marshal.go.tmpl | 32 +++++++++++++------ 9 files changed, 199 insertions(+), 73 deletions(-) diff --git a/constraint/babybear/marshal.go b/constraint/babybear/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/babybear/marshal.go +++ b/constraint/babybear/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/constraint/bls12-377/marshal.go b/constraint/bls12-377/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/bls12-377/marshal.go +++ b/constraint/bls12-377/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/constraint/bls12-381/marshal.go b/constraint/bls12-381/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/bls12-381/marshal.go +++ b/constraint/bls12-381/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/constraint/bn254/marshal.go b/constraint/bn254/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/bn254/marshal.go +++ b/constraint/bn254/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/constraint/bw6-761/marshal.go b/constraint/bw6-761/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/bw6-761/marshal.go +++ b/constraint/bw6-761/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/constraint/grumpkin/marshal.go b/constraint/grumpkin/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/grumpkin/marshal.go +++ b/constraint/grumpkin/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/constraint/koalabear/marshal.go b/constraint/koalabear/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/koalabear/marshal.go +++ b/constraint/koalabear/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/constraint/tinyfield/marshal.go b/constraint/tinyfield/marshal.go index 68bbdb092f..0a0521fa33 100644 --- a/constraint/tinyfield/marshal.go +++ b/constraint/tinyfield/marshal.go @@ -6,15 +6,24 @@ package cs import ( + "context" "encoding/binary" "fmt" "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -40,18 +49,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -76,11 +90,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err diff --git a/internal/generator/backend/template/representations/marshal.go.tmpl b/internal/generator/backend/template/representations/marshal.go.tmpl index 95456fc9cd..3a655ab2df 100644 --- a/internal/generator/backend/template/representations/marshal.go.tmpl +++ b/internal/generator/backend/template/representations/marshal.go.tmpl @@ -1,13 +1,22 @@ import ( - "io" + "context" "encoding/binary" "fmt" + "io" + "log/slog" + "time" "github.com/blang/semver/v4" + "github.com/consensys/gnark/internal/logger" ) // WriteTo encodes R1CS into provided io.Writer using cbor -func (cs *system) WriteTo(w io.Writer) (int64, error) { +func (cs *system) WriteTo(w io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "serialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + b, err := cs.System.ToBytes() if err != nil { return 0, err @@ -33,18 +42,23 @@ func (cs *system) WriteTo(w io.Writer) (int64, error) { } // write the system - n, err := w.Write(b) + writtenSystem, err := w.Write(b) if err != nil { - return int64(n), err + return int64(writtenSystem), err } // write the coeff table - m, err := w.Write(c) - return int64(n+m) + 4*8, err + writtenCoeffs, err := w.Write(c) + return int64(writtenSystem+writtenCoeffs) + 4*8, err } // ReadFrom attempts to decode R1CS from io.Reader using cbor -func (cs *system) ReadFrom(r io.Reader) (int64, error) { +func (cs *system) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "deserialize constraint system", slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + }() + var totalLen uint64 if err := binary.Read(r, binary.LittleEndian, &totalLen); err != nil { return 0, err @@ -69,11 +83,11 @@ func (cs *system) ReadFrom(r io.Reader) (int64, error) { if _, err := io.ReadFull(r, data); err != nil { return 0, err } - n, err := cs.System.FromBytes(data) + readSystem, err := cs.System.FromBytes(data) if err != nil { return 0, err } - data = data[n:] + data = data[readSystem:] if err := cs.CoeffTable.fromBytes(data); err != nil { return 0, err From 99096ee3af128cdc9006376c4226bb8164fbf4e6 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 23:16:17 +0000 Subject: [PATCH 41/44] feat: plonk serialization logs --- backend/plonk/bls12-377/marshal.go | 64 +++++++++++++++---- backend/plonk/bls12-381/marshal.go | 64 +++++++++++++++---- backend/plonk/bn254/marshal.go | 64 +++++++++++++++---- backend/plonk/bw6-761/marshal.go | 64 +++++++++++++++---- .../zkpschemes/plonk/plonk.marshal.go.tmpl | 64 +++++++++++++++---- 5 files changed, 265 insertions(+), 55 deletions(-) diff --git a/backend/plonk/bls12-377/marshal.go b/backend/plonk/bls12-377/marshal.go index f9e29c1b93..307f75d3c8 100644 --- a/backend/plonk/bls12-377/marshal.go +++ b/backend/plonk/bls12-377/marshal.go @@ -6,15 +6,25 @@ package plonk import ( + "context" "fmt" curve "github.com/consensys/gnark-crypto/ecc/bls12-377" "io" + "log/slog" + "time" "github.com/consensys/gnark-crypto/ecc/bls12-377/kzg" + + "github.com/consensys/gnark/internal/logger" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteRawTo writes binary encoding of Proof to w without point compression func (proof *Proof) WriteRawTo(w io.Writer) (int64, error) { return proof.writeTo(w, curve.RawEncoding()) @@ -25,7 +35,12 @@ func (proof *Proof) WriteTo(w io.Writer) (int64, error) { return proof.writeTo(w) } -func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) toEncode := []interface{}{ @@ -53,7 +68,12 @@ func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64 } // ReadFrom reads binary representation of Proof from r -func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { +func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() + dec := curve.NewDecoder(r) toDecode := []interface{}{ &proof.LRO[0], @@ -71,7 +91,7 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -80,7 +100,8 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { proof.Bsb22Commitments = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } // WriteTo writes binary encoding of ProvingKey to w @@ -94,6 +115,11 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { } func (pk *ProvingKey) writeTo(w io.Writer, withCompression bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", !withCompression)) + }() + // encode the verifying key if withCompression { n, err = pk.Vk.WriteTo(w) @@ -138,9 +164,14 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, false) } -func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (int64, error) { +func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", withSubgroupChecks)) + }() + pk.Vk = &VerifyingKey{} - n, err := pk.Vk.ReadFrom(r) + n, err = pk.Vk.ReadFrom(r) if err != nil { return n, err } @@ -175,6 +206,11 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error) { } func (vk *VerifyingKey) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) vk.version = currentKeyVersion @@ -226,17 +262,22 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { // decodes it accordingly. // // An error is returned if the encoded version is not supported. -func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { +func (vk *VerifyingKey) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key")) + }() + dec := curve.NewDecoder(r) var firstWord uint64 - if err := dec.Decode(&firstWord); err != nil { + if err = dec.Decode(&firstWord); err != nil { return dec.BytesRead(), err } var toDecode []interface{} if firstWord == keyVersionMarker { var version uint64 - if err := dec.Decode(&version); err != nil { + if err = dec.Decode(&version); err != nil { return dec.BytesRead(), err } @@ -293,7 +334,7 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -302,5 +343,6 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { vk.Qcp = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } diff --git a/backend/plonk/bls12-381/marshal.go b/backend/plonk/bls12-381/marshal.go index ef6e74f505..db7c6b653a 100644 --- a/backend/plonk/bls12-381/marshal.go +++ b/backend/plonk/bls12-381/marshal.go @@ -6,15 +6,25 @@ package plonk import ( + "context" "fmt" curve "github.com/consensys/gnark-crypto/ecc/bls12-381" "io" + "log/slog" + "time" "github.com/consensys/gnark-crypto/ecc/bls12-381/kzg" + + "github.com/consensys/gnark/internal/logger" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteRawTo writes binary encoding of Proof to w without point compression func (proof *Proof) WriteRawTo(w io.Writer) (int64, error) { return proof.writeTo(w, curve.RawEncoding()) @@ -25,7 +35,12 @@ func (proof *Proof) WriteTo(w io.Writer) (int64, error) { return proof.writeTo(w) } -func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) toEncode := []interface{}{ @@ -53,7 +68,12 @@ func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64 } // ReadFrom reads binary representation of Proof from r -func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { +func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() + dec := curve.NewDecoder(r) toDecode := []interface{}{ &proof.LRO[0], @@ -71,7 +91,7 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -80,7 +100,8 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { proof.Bsb22Commitments = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } // WriteTo writes binary encoding of ProvingKey to w @@ -94,6 +115,11 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { } func (pk *ProvingKey) writeTo(w io.Writer, withCompression bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", !withCompression)) + }() + // encode the verifying key if withCompression { n, err = pk.Vk.WriteTo(w) @@ -138,9 +164,14 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, false) } -func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (int64, error) { +func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", withSubgroupChecks)) + }() + pk.Vk = &VerifyingKey{} - n, err := pk.Vk.ReadFrom(r) + n, err = pk.Vk.ReadFrom(r) if err != nil { return n, err } @@ -175,6 +206,11 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error) { } func (vk *VerifyingKey) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) vk.version = currentKeyVersion @@ -226,17 +262,22 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { // decodes it accordingly. // // An error is returned if the encoded version is not supported. -func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { +func (vk *VerifyingKey) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key")) + }() + dec := curve.NewDecoder(r) var firstWord uint64 - if err := dec.Decode(&firstWord); err != nil { + if err = dec.Decode(&firstWord); err != nil { return dec.BytesRead(), err } var toDecode []interface{} if firstWord == keyVersionMarker { var version uint64 - if err := dec.Decode(&version); err != nil { + if err = dec.Decode(&version); err != nil { return dec.BytesRead(), err } @@ -293,7 +334,7 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -302,5 +343,6 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { vk.Qcp = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } diff --git a/backend/plonk/bn254/marshal.go b/backend/plonk/bn254/marshal.go index 7ddadd0f83..10853ebaca 100644 --- a/backend/plonk/bn254/marshal.go +++ b/backend/plonk/bn254/marshal.go @@ -6,15 +6,25 @@ package plonk import ( + "context" "fmt" curve "github.com/consensys/gnark-crypto/ecc/bn254" "io" + "log/slog" + "time" "github.com/consensys/gnark-crypto/ecc/bn254/kzg" + + "github.com/consensys/gnark/internal/logger" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteRawTo writes binary encoding of Proof to w without point compression func (proof *Proof) WriteRawTo(w io.Writer) (int64, error) { return proof.writeTo(w, curve.RawEncoding()) @@ -25,7 +35,12 @@ func (proof *Proof) WriteTo(w io.Writer) (int64, error) { return proof.writeTo(w) } -func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) toEncode := []interface{}{ @@ -53,7 +68,12 @@ func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64 } // ReadFrom reads binary representation of Proof from r -func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { +func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() + dec := curve.NewDecoder(r) toDecode := []interface{}{ &proof.LRO[0], @@ -71,7 +91,7 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -80,7 +100,8 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { proof.Bsb22Commitments = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } // WriteTo writes binary encoding of ProvingKey to w @@ -94,6 +115,11 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { } func (pk *ProvingKey) writeTo(w io.Writer, withCompression bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", !withCompression)) + }() + // encode the verifying key if withCompression { n, err = pk.Vk.WriteTo(w) @@ -138,9 +164,14 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, false) } -func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (int64, error) { +func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", withSubgroupChecks)) + }() + pk.Vk = &VerifyingKey{} - n, err := pk.Vk.ReadFrom(r) + n, err = pk.Vk.ReadFrom(r) if err != nil { return n, err } @@ -175,6 +206,11 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error) { } func (vk *VerifyingKey) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) vk.version = currentKeyVersion @@ -226,17 +262,22 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { // decodes it accordingly. // // An error is returned if the encoded version is not supported. -func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { +func (vk *VerifyingKey) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key")) + }() + dec := curve.NewDecoder(r) var firstWord uint64 - if err := dec.Decode(&firstWord); err != nil { + if err = dec.Decode(&firstWord); err != nil { return dec.BytesRead(), err } var toDecode []interface{} if firstWord == keyVersionMarker { var version uint64 - if err := dec.Decode(&version); err != nil { + if err = dec.Decode(&version); err != nil { return dec.BytesRead(), err } @@ -293,7 +334,7 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -302,5 +343,6 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { vk.Qcp = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } diff --git a/backend/plonk/bw6-761/marshal.go b/backend/plonk/bw6-761/marshal.go index e6a315c9c9..a4585bb519 100644 --- a/backend/plonk/bw6-761/marshal.go +++ b/backend/plonk/bw6-761/marshal.go @@ -6,15 +6,25 @@ package plonk import ( + "context" "fmt" curve "github.com/consensys/gnark-crypto/ecc/bw6-761" "io" + "log/slog" + "time" "github.com/consensys/gnark-crypto/ecc/bw6-761/kzg" + + "github.com/consensys/gnark/internal/logger" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteRawTo writes binary encoding of Proof to w without point compression func (proof *Proof) WriteRawTo(w io.Writer) (int64, error) { return proof.writeTo(w, curve.RawEncoding()) @@ -25,7 +35,12 @@ func (proof *Proof) WriteTo(w io.Writer) (int64, error) { return proof.writeTo(w) } -func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) toEncode := []interface{}{ @@ -53,7 +68,12 @@ func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64 } // ReadFrom reads binary representation of Proof from r -func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { +func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() + dec := curve.NewDecoder(r) toDecode := []interface{}{ &proof.LRO[0], @@ -71,7 +91,7 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -80,7 +100,8 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { proof.Bsb22Commitments = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } // WriteTo writes binary encoding of ProvingKey to w @@ -94,6 +115,11 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { } func (pk *ProvingKey) writeTo(w io.Writer, withCompression bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", !withCompression)) + }() + // encode the verifying key if withCompression { n, err = pk.Vk.WriteTo(w) @@ -138,9 +164,14 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, false) } -func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (int64, error) { +func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", withSubgroupChecks)) + }() + pk.Vk = &VerifyingKey{} - n, err := pk.Vk.ReadFrom(r) + n, err = pk.Vk.ReadFrom(r) if err != nil { return n, err } @@ -175,6 +206,11 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error) { } func (vk *VerifyingKey) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) vk.version = currentKeyVersion @@ -226,17 +262,22 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { // decodes it accordingly. // // An error is returned if the encoded version is not supported. -func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { +func (vk *VerifyingKey) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key")) + }() + dec := curve.NewDecoder(r) var firstWord uint64 - if err := dec.Decode(&firstWord); err != nil { + if err = dec.Decode(&firstWord); err != nil { return dec.BytesRead(), err } var toDecode []interface{} if firstWord == keyVersionMarker { var version uint64 - if err := dec.Decode(&version); err != nil { + if err = dec.Decode(&version); err != nil { return dec.BytesRead(), err } @@ -293,7 +334,7 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -302,5 +343,6 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { vk.Qcp = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } diff --git a/internal/generator/backend/template/zkpschemes/plonk/plonk.marshal.go.tmpl b/internal/generator/backend/template/zkpschemes/plonk/plonk.marshal.go.tmpl index 8591004efb..17f87a73f5 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.marshal.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.marshal.go.tmpl @@ -1,10 +1,20 @@ import ( {{ template "import_curve" . }} + "context" "fmt" {{ template "import_kzg" . }} "io" + "log/slog" + "time" + + "github.com/consensys/gnark/internal/logger" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteRawTo writes binary encoding of Proof to w without point compression func (proof *Proof) WriteRawTo(w io.Writer) (int64, error) { return proof.writeTo(w, curve.RawEncoding()) @@ -15,7 +25,12 @@ func (proof *Proof) WriteTo(w io.Writer) (int64, error) { return proof.writeTo(w) } -func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64, error) { +func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proof"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) toEncode := []interface{}{ @@ -43,7 +58,12 @@ func (proof *Proof) writeTo(w io.Writer, options ...func(*curve.Encoder)) (int64 } // ReadFrom reads binary representation of Proof from r -func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { +func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proof")) + }() + dec := curve.NewDecoder(r) toDecode := []interface{}{ &proof.LRO[0], @@ -61,7 +81,7 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -70,7 +90,8 @@ func (proof *Proof) ReadFrom(r io.Reader) (int64, error) { proof.Bsb22Commitments = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } // WriteTo writes binary encoding of ProvingKey to w @@ -84,6 +105,11 @@ func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { } func (pk *ProvingKey) writeTo(w io.Writer, withCompression bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "proving_key"), slog.Bool("raw", !withCompression)) + }() + // encode the verifying key if withCompression { n, err = pk.Vk.WriteTo(w) @@ -129,9 +155,14 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { return pk.readFrom(r, false) } -func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (int64, error) { +func (pk *ProvingKey) readFrom(r io.Reader, withSubgroupChecks bool) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "proving_key"), slog.Bool("subgroup_checks", withSubgroupChecks)) + }() + pk.Vk = &VerifyingKey{} - n, err := pk.Vk.ReadFrom(r) + n, err = pk.Vk.ReadFrom(r) if err != nil { return n, err } @@ -166,6 +197,11 @@ func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error) { } func (vk *VerifyingKey) writeTo(w io.Writer, options ...func(*curve.Encoder)) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "serialize"), slog.String("object", "verifying_key"), slog.Bool("raw", len(options) != 0)) + }() + enc := curve.NewEncoder(w, options...) vk.version = currentKeyVersion @@ -217,17 +253,22 @@ func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { // decodes it accordingly. // // An error is returned if the encoded version is not supported. -func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { +func (vk *VerifyingKey) ReadFrom(r io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "plonk"), slog.String("operation", "deserialize"), slog.String("object", "verifying_key")) + }() + dec := curve.NewDecoder(r) var firstWord uint64 - if err := dec.Decode(&firstWord); err != nil { + if err = dec.Decode(&firstWord); err != nil { return dec.BytesRead(), err } var toDecode []interface{} if firstWord == keyVersionMarker { var version uint64 - if err := dec.Decode(&version); err != nil { + if err = dec.Decode(&version); err != nil { return dec.BytesRead(), err } @@ -284,7 +325,7 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { } for _, v := range toDecode { - if err := dec.Decode(v); err != nil { + if err = dec.Decode(v); err != nil { return dec.BytesRead(), err } } @@ -293,5 +334,6 @@ func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { vk.Qcp = []kzg.Digest{} } - return dec.BytesRead(), nil + n = dec.BytesRead() + return n, nil } From 548b79edafca163799be786fccf05379191c9382 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Wed, 20 May 2026 23:17:09 +0000 Subject: [PATCH 42/44] feat: mpcsetup log marshal with debug --- backend/groth16/bls12-377/mpcsetup/marshal.go | 41 ++++++++++++++++- backend/groth16/bls12-381/mpcsetup/marshal.go | 41 ++++++++++++++++- backend/groth16/bn254/mpcsetup/marshal.go | 41 ++++++++++++++++- backend/groth16/bw6-761/mpcsetup/marshal.go | 41 ++++++++++++++++- .../groth16/mpcsetup/marshal.go.tmpl | 46 +++++++++++++++++-- 5 files changed, 203 insertions(+), 7 deletions(-) diff --git a/backend/groth16/bls12-377/mpcsetup/marshal.go b/backend/groth16/bls12-377/mpcsetup/marshal.go index 94c84c9b16..7071b53722 100644 --- a/backend/groth16/bls12-377/mpcsetup/marshal.go +++ b/backend/groth16/bls12-377/mpcsetup/marshal.go @@ -6,17 +6,31 @@ package mpcsetup import ( + "context" "encoding/binary" "io" + "log/slog" + "time" curve "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/mpcsetup" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" gIo "github.com/consensys/gnark/io" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo implements io.WriterTo func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.WriterTo{ &p.proofs.Tau, @@ -37,6 +51,11 @@ func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase1) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.ReaderFrom{ &p.proofs.Tau, @@ -82,6 +101,11 @@ func (p *Phase2) refsSlice() []any { // WriteTo implements io.WriterTo func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase2")) + }() + // write the parameters if err = binary.Write(writer, binary.BigEndian, uint16(len(p.Parameters.G2.Sigma))); err != nil { return -1, err // binary.Write doesn't return the number of bytes written @@ -115,6 +139,11 @@ func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase2) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase2")) + }() + var nbCommitments uint16 if err = binary.Read(reader, binary.BigEndian, &nbCommitments); err != nil { @@ -178,7 +207,12 @@ func (c *SrsCommons) refsSlice() []any { return refs } -func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { +func (c *SrsCommons) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_srs_commons")) + }() + enc := curve.NewEncoder(writer) for _, v := range c.refsSlice() { if err := enc.Encode(v); err != nil { @@ -190,6 +224,11 @@ func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { // ReadFrom implements io.ReaderFrom func (c *SrsCommons) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_srs_commons")) + }() + var N uint64 dec := curve.NewDecoder(reader) if err = dec.Decode(&N); err != nil { diff --git a/backend/groth16/bls12-381/mpcsetup/marshal.go b/backend/groth16/bls12-381/mpcsetup/marshal.go index 41b31066f1..6ca536d099 100644 --- a/backend/groth16/bls12-381/mpcsetup/marshal.go +++ b/backend/groth16/bls12-381/mpcsetup/marshal.go @@ -6,17 +6,31 @@ package mpcsetup import ( + "context" "encoding/binary" "io" + "log/slog" + "time" curve "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/mpcsetup" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" gIo "github.com/consensys/gnark/io" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo implements io.WriterTo func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.WriterTo{ &p.proofs.Tau, @@ -37,6 +51,11 @@ func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase1) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.ReaderFrom{ &p.proofs.Tau, @@ -82,6 +101,11 @@ func (p *Phase2) refsSlice() []any { // WriteTo implements io.WriterTo func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase2")) + }() + // write the parameters if err = binary.Write(writer, binary.BigEndian, uint16(len(p.Parameters.G2.Sigma))); err != nil { return -1, err // binary.Write doesn't return the number of bytes written @@ -115,6 +139,11 @@ func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase2) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase2")) + }() + var nbCommitments uint16 if err = binary.Read(reader, binary.BigEndian, &nbCommitments); err != nil { @@ -178,7 +207,12 @@ func (c *SrsCommons) refsSlice() []any { return refs } -func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { +func (c *SrsCommons) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_srs_commons")) + }() + enc := curve.NewEncoder(writer) for _, v := range c.refsSlice() { if err := enc.Encode(v); err != nil { @@ -190,6 +224,11 @@ func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { // ReadFrom implements io.ReaderFrom func (c *SrsCommons) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_srs_commons")) + }() + var N uint64 dec := curve.NewDecoder(reader) if err = dec.Decode(&N); err != nil { diff --git a/backend/groth16/bn254/mpcsetup/marshal.go b/backend/groth16/bn254/mpcsetup/marshal.go index abc369dc55..8c22c4d76b 100644 --- a/backend/groth16/bn254/mpcsetup/marshal.go +++ b/backend/groth16/bn254/mpcsetup/marshal.go @@ -6,17 +6,31 @@ package mpcsetup import ( + "context" "encoding/binary" "io" + "log/slog" + "time" curve "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/mpcsetup" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" gIo "github.com/consensys/gnark/io" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo implements io.WriterTo func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.WriterTo{ &p.proofs.Tau, @@ -37,6 +51,11 @@ func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase1) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.ReaderFrom{ &p.proofs.Tau, @@ -82,6 +101,11 @@ func (p *Phase2) refsSlice() []any { // WriteTo implements io.WriterTo func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase2")) + }() + // write the parameters if err = binary.Write(writer, binary.BigEndian, uint16(len(p.Parameters.G2.Sigma))); err != nil { return -1, err // binary.Write doesn't return the number of bytes written @@ -115,6 +139,11 @@ func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase2) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase2")) + }() + var nbCommitments uint16 if err = binary.Read(reader, binary.BigEndian, &nbCommitments); err != nil { @@ -178,7 +207,12 @@ func (c *SrsCommons) refsSlice() []any { return refs } -func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { +func (c *SrsCommons) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_srs_commons")) + }() + enc := curve.NewEncoder(writer) for _, v := range c.refsSlice() { if err := enc.Encode(v); err != nil { @@ -190,6 +224,11 @@ func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { // ReadFrom implements io.ReaderFrom func (c *SrsCommons) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_srs_commons")) + }() + var N uint64 dec := curve.NewDecoder(reader) if err = dec.Decode(&N); err != nil { diff --git a/backend/groth16/bw6-761/mpcsetup/marshal.go b/backend/groth16/bw6-761/mpcsetup/marshal.go index d6993b0781..f81a5a1ddc 100644 --- a/backend/groth16/bw6-761/mpcsetup/marshal.go +++ b/backend/groth16/bw6-761/mpcsetup/marshal.go @@ -6,17 +6,31 @@ package mpcsetup import ( + "context" "encoding/binary" "io" + "log/slog" + "time" curve "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/mpcsetup" + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" gIo "github.com/consensys/gnark/io" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo implements io.WriterTo func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.WriterTo{ &p.proofs.Tau, @@ -37,6 +51,11 @@ func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase1) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.ReaderFrom{ &p.proofs.Tau, @@ -82,6 +101,11 @@ func (p *Phase2) refsSlice() []any { // WriteTo implements io.WriterTo func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase2")) + }() + // write the parameters if err = binary.Write(writer, binary.BigEndian, uint16(len(p.Parameters.G2.Sigma))); err != nil { return -1, err // binary.Write doesn't return the number of bytes written @@ -115,6 +139,11 @@ func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase2) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase2")) + }() + var nbCommitments uint16 if err = binary.Read(reader, binary.BigEndian, &nbCommitments); err != nil { @@ -178,7 +207,12 @@ func (c *SrsCommons) refsSlice() []any { return refs } -func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { +func (c *SrsCommons) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_srs_commons")) + }() + enc := curve.NewEncoder(writer) for _, v := range c.refsSlice() { if err := enc.Encode(v); err != nil { @@ -190,6 +224,11 @@ func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { // ReadFrom implements io.ReaderFrom func (c *SrsCommons) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_srs_commons")) + }() + var N uint64 dec := curve.NewDecoder(reader) if err = dec.Decode(&N); err != nil { diff --git a/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/marshal.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/marshal.go.tmpl index 38b4dbb629..835ca11641 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/marshal.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/marshal.go.tmpl @@ -1,6 +1,11 @@ import ( - "io" + "context" "encoding/binary" + "io" + "log/slog" + "time" + + "github.com/consensys/gnark/internal/logger" "github.com/consensys/gnark/internal/utils" gIo "github.com/consensys/gnark/io" @@ -8,8 +13,18 @@ import ( "github.com/consensys/gnark-crypto/ecc/{{toLower .Curve}}/mpcsetup" ) +func logSerializationDebug(start time.Time, n int64, err error, attrs ...slog.Attr) { + attrs = append(attrs, slog.Duration("took", time.Since(start)), slog.Int64("bytes", n), slog.Bool("success", err == nil)) + logger.Logger().LogAttrs(context.Background(), slog.LevelDebug, "backend serialization", attrs...) +} + // WriteTo implements io.WriterTo func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.WriterTo{ &p.proofs.Tau, @@ -30,6 +45,11 @@ func (p *Phase1) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase1) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase1")) + }() + var dn int64 for _, v := range []io.ReaderFrom{ &p.proofs.Tau, @@ -75,6 +95,11 @@ func (p *Phase2) refsSlice() []any { // WriteTo implements io.WriterTo func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_phase2")) + }() + // write the parameters if err = binary.Write(writer, binary.BigEndian, uint16(len(p.Parameters.G2.Sigma))); err != nil { return -1, err // binary.Write doesn't return the number of bytes written @@ -108,6 +133,11 @@ func (p *Phase2) WriteTo(writer io.Writer) (n int64, err error) { // ReadFrom implements io.ReaderFrom func (p *Phase2) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_phase2")) + }() + var nbCommitments uint16 if err = binary.Read(reader, binary.BigEndian, &nbCommitments); err != nil { @@ -171,7 +201,12 @@ func (c *SrsCommons) refsSlice() []any { return refs } -func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { +func (c *SrsCommons) WriteTo(writer io.Writer) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "serialize"), slog.String("object", "mpc_srs_commons")) + }() + enc := curve.NewEncoder(writer) for _, v := range c.refsSlice() { if err := enc.Encode(v); err != nil { @@ -183,6 +218,11 @@ func (c *SrsCommons) WriteTo(writer io.Writer) (int64, error) { // ReadFrom implements io.ReaderFrom func (c *SrsCommons) ReadFrom(reader io.Reader) (n int64, err error) { + start := time.Now() + defer func() { + logSerializationDebug(start, n, err, slog.String("backend", "groth16"), slog.String("operation", "deserialize"), slog.String("object", "mpc_srs_commons")) + }() + var N uint64 dec := curve.NewDecoder(reader) if err = dec.Decode(&N); err != nil { @@ -197,4 +237,4 @@ func (c *SrsCommons) ReadFrom(reader io.Reader) (n int64, err error) { } } return dec.BytesRead(), nil -} \ No newline at end of file +} From 1a58d1f855044d1c2dc0de9ae81e594e4c12d0db Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Mon, 25 May 2026 08:15:17 +0000 Subject: [PATCH 43/44] fix: avoid string formatting in slog --- backend/accelerated/icicle/groth16/bls12-377/icicle.go | 6 +++--- backend/accelerated/icicle/groth16/bls12-381/icicle.go | 6 +++--- backend/accelerated/icicle/groth16/bn254/icicle.go | 6 +++--- backend/accelerated/icicle/groth16/bw6-761/icicle.go | 6 +++--- .../internal/generator/templates/groth16.icicle.go.tmpl | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/backend/accelerated/icicle/groth16/bls12-377/icicle.go b/backend/accelerated/icicle/groth16/bls12-377/icicle.go index ef71835347..0dbb93cb6e 100644 --- a/backend/accelerated/icicle/groth16/bls12-377/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-377/icicle.go @@ -1351,13 +1351,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesADevice"), slog.String("error", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesBDevice"), slog.String("error", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "h"), slog.String("error", err.AsString())) } }) diff --git a/backend/accelerated/icicle/groth16/bls12-381/icicle.go b/backend/accelerated/icicle/groth16/bls12-381/icicle.go index 1d86e9955a..b5641fc532 100644 --- a/backend/accelerated/icicle/groth16/bls12-381/icicle.go +++ b/backend/accelerated/icicle/groth16/bls12-381/icicle.go @@ -1351,13 +1351,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesADevice"), slog.String("error", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesBDevice"), slog.String("error", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "h"), slog.String("error", err.AsString())) } }) diff --git a/backend/accelerated/icicle/groth16/bn254/icicle.go b/backend/accelerated/icicle/groth16/bn254/icicle.go index 237d51e213..383e0a49c4 100644 --- a/backend/accelerated/icicle/groth16/bn254/icicle.go +++ b/backend/accelerated/icicle/groth16/bn254/icicle.go @@ -1351,13 +1351,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesADevice"), slog.String("error", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesBDevice"), slog.String("error", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "h"), slog.String("error", err.AsString())) } }) diff --git a/backend/accelerated/icicle/groth16/bw6-761/icicle.go b/backend/accelerated/icicle/groth16/bw6-761/icicle.go index 0407949a5e..c95fda52ca 100644 --- a/backend/accelerated/icicle/groth16/bw6-761/icicle.go +++ b/backend/accelerated/icicle/groth16/bw6-761/icicle.go @@ -1340,13 +1340,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesADevice"), slog.String("error", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesBDevice"), slog.String("error", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "h"), slog.String("error", err.AsString())) } }) diff --git a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl index f49d5cc9fe..da12b35d02 100644 --- a/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl +++ b/backend/accelerated/icicle/internal/generator/templates/groth16.icicle.go.tmpl @@ -1364,13 +1364,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, cfg *icic // free device/GPU memory that is not needed for future proofs (scalars/hpoly) icicle_runtime.RunOnDevice(&device, func(args ...any) { if err := wireValuesADevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesADevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesADevice"), slog.String("error", err.AsString())) } if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free wireValuesBDevice failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "wireValuesBDevice"), slog.String("error", err.AsString())) } if err := h.Free(); err != icicle_runtime.Success { - log.Error(fmt.Sprintf("free h failed: %s", err.AsString())) + log.Error("free device memory failed", slog.String("buffer", "h"), slog.String("error", err.AsString())) } }) From f9db4703388286516bb34bf0f18165cb1527ade5 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Thu, 11 Jun 2026 11:04:50 +0000 Subject: [PATCH 44/44] chore: use new logger in ICICLE Groth16 dispatcher --- backend/accelerated/icicle/groth16/groth16_icicle.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/accelerated/icicle/groth16/groth16_icicle.go b/backend/accelerated/icicle/groth16/groth16_icicle.go index 06e046b378..7e85f906b7 100644 --- a/backend/accelerated/icicle/groth16/groth16_icicle.go +++ b/backend/accelerated/icicle/groth16/groth16_icicle.go @@ -4,6 +4,7 @@ package groth16 import ( "fmt" + "log/slog" "sync" "github.com/consensys/gnark-crypto/ecc" @@ -18,7 +19,7 @@ import ( cs_bls12381 "github.com/consensys/gnark/constraint/bls12-381" cs_bn254 "github.com/consensys/gnark/constraint/bn254" cs_bw6761 "github.com/consensys/gnark/constraint/bw6-761" - "github.com/consensys/gnark/logger" + "github.com/consensys/gnark/internal/logger" icicle_bls12377 "github.com/consensys/gnark/backend/accelerated/icicle/groth16/bls12-377" icicle_bls12381 "github.com/consensys/gnark/backend/accelerated/icicle/groth16/bls12-381" @@ -53,10 +54,10 @@ func warmUpDevice(config *icicle.Config) { if err != icicle_runtime.Success { panic(fmt.Sprintf("ICICLE get device count error: %s", err.AsString())) } - log.Debug().Int("nbDev", nbDev).Msg("ICICLE devices detected") + log.Debug("ICICLE devices detected", slog.Int("nbDev", nbDev)) for id := 0; id < nbDev; id++ { device := icicle_runtime.CreateDevice(config.Backend.String(), id) - log.Debug().Int32("id", device.Id).Str("type", device.GetDeviceType()).Msg("ICICLE device created") + log.Debug("ICICLE device created", slog.Int("id", int(device.Id)), slog.String("type", device.GetDeviceType())) icicle_runtime.RunOnDevice(&device, func(args ...any) { stream, err := icicle_runtime.CreateStream() if err != icicle_runtime.Success {