Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion prover-ray/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.25.7
require (
github.com/consensys/gnark v0.14.1-0.20260219004710-bbfb2f70a565
github.com/consensys/gnark-crypto v0.20.2-0.20260514182922-df0578435b08
github.com/consensys/go-corset v1.2.10
github.com/consensys/go-corset v1.2.17
github.com/go-playground/assert/v2 v2.2.0
github.com/sirupsen/logrus v1.9.4
github.com/stretchr/testify v1.11.1
Expand Down
4 changes: 2 additions & 2 deletions prover-ray/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ github.com/consensys/gnark v0.14.1-0.20260219004710-bbfb2f70a565 h1:NlOAmbLYsVb/
github.com/consensys/gnark v0.14.1-0.20260219004710-bbfb2f70a565/go.mod h1:EoWWbEboQRydCqJDSA7zrFxucIeoy/5R+MDx04oFpF4=
github.com/consensys/gnark-crypto v0.20.2-0.20260514182922-df0578435b08 h1:EdljQKaHxACX5JMSTXlVM9R8qASU/W1husqDsB2b5tU=
github.com/consensys/gnark-crypto v0.20.2-0.20260514182922-df0578435b08/go.mod h1:NzeBHSZ49bIM7RtrNTYYR2kymTqwvI/A4eTgQlyQc+Q=
github.com/consensys/go-corset v1.2.10 h1:uKUICiHmERuMWzDRiRJr285fV2WncNGiCENSdNcQodY=
github.com/consensys/go-corset v1.2.10/go.mod h1:QKFoNJZHdCrDslg9XFjk+GoFMgrhKSVdBNnx4hq7WJA=
github.com/consensys/go-corset v1.2.17 h1:zy30Snj1JTQePoBzk8vEkAXUE1i7p0AdNHGxWwbdkC4=
github.com/consensys/go-corset v1.2.17/go.mod h1:QKFoNJZHdCrDslg9XFjk+GoFMgrhKSVdBNnx4hq7WJA=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
4 changes: 4 additions & 0 deletions prover-ray/wiop/wiop_column.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ func (m *Module) NewPrecomputedColumn(ctx *ContextFrame, vis Visibility, assignm
if ctx.ID != 0 {
panic(fmt.Sprintf("wiop: ContextFrame %q is already registered (id=%d)", ctx.Path(), ctx.ID))
}
if assignment.promise != nil {
panic("wiop: Module.NewPrecomputedColumn requires a non-promised assignment")
}
ctx.ID = newColumnID(m.index, len(m.Columns))
pr := m.system.PrecomputedRound
col := &Column{
Expand All @@ -182,6 +185,7 @@ func (m *Module) NewPrecomputedColumn(ctx *ContextFrame, vis Visibility, assignm
Module: m,
round: &pr.Round,
}
assignment.promise = col.View()
m.Columns = append(m.Columns, col)
pr.addPrecomputedColumn(col, assignment)
return col
Expand Down
20 changes: 15 additions & 5 deletions prover-ray/zkcdriver/assignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package zkcdriver
import (
"unsafe"

"github.com/consensys/go-corset/pkg/ir/air"
"github.com/consensys/go-corset/pkg/trace"
"github.com/consensys/go-corset/pkg/util/field/koalabear"
"github.com/consensys/linea-monorepo/prover-ray/maths/koalabear/field"
Expand All @@ -19,14 +20,23 @@ var _ [1]uint32 = field.Element{}

// ReadExpandedTraces parses the provided trace file, expands it and returns the
// corset object holding the expanded traces.
func AssignFromLtTraces(run *wiop.Runtime, expTraces trace.Trace[koalabear.Element]) {
func AssignFromTrace(run *wiop.Runtime, traces trace.Trace[koalabear.Element], schema air.Schema[koalabear.Element]) {

// Parallelize across modules
eg := &errgroup.Group{}
for modID := range expTraces.Width() {
for modID := range traces.Width() {
eg.Go(func() error {

trMod := expTraces.Module(modID)
trMod := traces.Module(modID)
scMod := schema.Module(modID)

if scMod.IsStatic() {
// @alex: the current version of corset flags modules as being
// static or not static. But it may be the case, that a module
// has static size, some its column have static content but some
// do not have static content.
return nil
}
Comment thread
cursor[bot] marked this conversation as resolved.

// Iterate each column in module
parallel.Execute(int(trMod.Width()), func(start, stop int) {
Expand All @@ -41,7 +51,7 @@ func AssignFromLtTraces(run *wiop.Runtime, expTraces trace.Trace[koalabear.Eleme
)

if _, ok := columnIDMap[name]; !ok {
logrus.Debugf("zkcdriver: AssignFromLtTraces: skipping unknown column %q", name)
logrus.Debugf("zkcdriver: AssignFromTrace: skipping unknown column %q", name)
continue
}

Expand Down Expand Up @@ -74,6 +84,6 @@ func AssignFromLtTraces(run *wiop.Runtime, expTraces trace.Trace[koalabear.Eleme
})
}
if err := eg.Wait(); err != nil {
logrus.Panicf("AssignFromLtTraces failed: %v", err)
logrus.Panicf("zkcdriver: AssignFromTrace failed: %v", err)
}
}
78 changes: 69 additions & 9 deletions prover-ray/zkcdriver/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/consensys/linea-monorepo/prover-ray/maths/koalabear/field"
"github.com/consensys/linea-monorepo/prover-ray/wiop"
"github.com/sirupsen/logrus"

"github.com/consensys/go-corset/pkg/ir/air"
"github.com/consensys/go-corset/pkg/schema"
Expand Down Expand Up @@ -64,17 +65,62 @@ func (s *schemaScanner) scanColumns() {
// Use the pre-sorted modules from the scanner to ensure deterministic ordering
// Iterate each declared module
for _, modDecl := range s.Modules {
// Check for special cases
if modDecl.IsStatic() {

content := modDecl.StaticContents()
moduleName := modDecl.Name().String()
moduleWIOP := s.Sys.NewSizedModule(
s.Sys.Context.Childf("module-%v", moduleName),
len(content),
wiop.PaddingDirectionLeft,
Comment thread
AlexandreBelling marked this conversation as resolved.
)

// This works assuming the [System] appends-only to the list of modules.
s.ModulesIDsWiop[moduleName] = len(s.Sys.Modules) - 1

for i, colDecl := range modDecl.Registers() {

vec := make([]field.Element, len(content))
for j := range content {
vec[j] = field.Element(content[j][i])
}

var (
colName = colDecl.Name()
colQualifiedName = qualifiedCorsetName(moduleName, colName)
col = moduleWIOP.NewPrecomputedColumn(
moduleWIOP.Context.Childf("column-%v", colName),
wiop.VisibilityOracle,
&wiop.ConcreteVector{Plain: field.VecFromBase(vec)},
)
)

// The "root" module is part of the if the list of the modules. It
// expectedly does not contains any column. We need to skip it because
// we would not be able to find its name.
if modDecl.Name().String() == "" {
if modDecl.Width() != 0 {
utils.Panic("found a module with no names but with columns")
s.ColumnIDs[colQualifiedName] = col.Context.ID
}

Comment thread
cursor[bot] marked this conversation as resolved.
continue
}

if modDecl.IsNative() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivokub @YaoJGalteland @Tabaie @arijitdutta67

This is meant to serve as entrypoint for the implementation of the precompiles, when they get added

// @david: need to add support for native modules. These correspond
// to ZkC functions declared with the "native" attribute". The
// expectation is that the prover will maintain a list of supported
// native modules. Each of these will have an expected number of
// columns (which the prover may wish to check matches the
// declaration here). These columns correspond to the input/output
// registers of the corresponding ZkC function.
//
// A key aspect of native modules is that ZkC will not generate any
// constraints for them. Instead, the expectation is that whatever
// constraints are required will be added somehow / somewhere by the
// prover. Since forgetting to do this is a critical soundness
// issue, care must be taken to ensure it really happens (e.g.
// through testing negative cases which should cause constraint
// failures).
logrus.Panic("zkcdriver: add support for native modules!")
}

// moduleName is the name of the module as given by the arithmetization
moduleName := modDecl.Name().String()
moduleWIOP := s.Sys.NewDynamicModule(
Expand Down Expand Up @@ -243,12 +289,26 @@ func (s *schemaScanner) addConstraintInComp(name string, corsetCS schema.Constra
module.NewVanishing(module.Context.Childf("local-%v", name), wExpr)

case air.RangeConstraint[koalabear.Element]:
utils.Panic("RangeConstraint is not yet supported (constraint: %s)", name)

rc := cs.Unwrap()

// Sanity check: If a RangeConstraint ever has more than one source/bitwidth, the second iteration will panic
// because the first iteration already registered that QueryID in the CompiledIOP. In practice
// the len is always expected to be either 0 (no-op) or 1 (single pass).
if len(rc.Bitwidths) > 1 {
utils.Panic("multiple bitwidths for range constraints not supported")
}

for i, bitwidth := range rc.Bitwidths {
// Determine bound for this range constraint
bound := 1 << bitwidth
col := s.compColumnByCorsetID(rc.Context, rc.Sources[i].Register())
col.Module.NewRangeCheck(col.Context.Childf("range-%v", name), col, bound)
}

case air.Assertion[koalabear.Element]:
// Property assertions can be ignored, as they are a debugging tool and
// not part of the constraints proper.
case air.InterleavingConstraint[koalabear.Element]:
panic("to be removed once corset, removes it. We will never support this.")

default:
utils.Panic("unexpected constraint type: %s", cs.Lisp(s.Schema).String(false))
Expand Down
24 changes: 0 additions & 24 deletions prover-ray/zkcdriver/definition_test.go

This file was deleted.

83 changes: 83 additions & 0 deletions prover-ray/zkcdriver/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package zkcdriver_test

import (
"fmt"
"testing"

zkc_util "github.com/consensys/go-corset/pkg/zkc/util"
"github.com/consensys/linea-monorepo/prover-ray/utils/files"
"github.com/consensys/linea-monorepo/prover-ray/wiop"
"github.com/consensys/linea-monorepo/prover-ray/wiop/wioptest"
"github.com/consensys/linea-monorepo/prover-ray/zkcdriver"
)

func TestZkc_01a(t *testing.T) {
runTest(t, "zkc_01", "{\"data\": \"0x0000_0001\" }")
}

func TestZkc_01b(t *testing.T) {
runTest(t, "zkc_01", "{\"data\": \"0x0041_0042\" }")
}

func TestZkc_02a(t *testing.T) {
runTest(t, "zkc_02", "{\"data\": \"0x0003_0008\" }")
}

func TestZkc_02b(t *testing.T) {
runTest(t, "zkc_02", "{\"data\": \"0x000f_8000\" }")
}

// nolint
func runTest(t *testing.T, test, input string) {
sys := wiop.NewSystemf("zkc-test")
// set an example input
var (
testfile = fmt.Sprintf("./testdata/%s.bin", test)
// construct inputs map
inputs zkcdriver.PreReadInputs
)
// parse example input
inputs.Inputs, inputs.Err = zkc_util.ParseJsonInputFile([]byte(input))
// Sanity check
if inputs.Err != nil {
t.Errorf("error parsing program inputs (%v)", inputs.Err)
t.FailNow()
}
// initialise round
sys.NewRound()
// construct ZkC driver
driver := zkcdriver.NewZkCDriver(
sys,
zkcdriver.Settings{},
files.MustRead(testfile))
rt := wiop.NewRuntime(sys)
driver.AssignWithPreRead(&rt, inputs)

if err := wioptest.RunAndVerify(&rt); err != nil {
t.Fatalf("error running verifier: %v", err)
}
// FIXME: run the prover to complete the test. For now, I just used
Comment thread
AlexandreBelling marked this conversation as resolved.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still have a FIXME here btw

// go-corset's internal check to illustrate how this can work (e.g. it might
// be useful for debugging). Run go-corset constraint check
runZkcConstraintCheck(t, driver, inputs.Inputs)
}

func runZkcConstraintCheck(t *testing.T, driver *zkcdriver.ZkCDriver, input map[string][]byte) {
t.Helper()
// trace program with given input
tr, errs := driver.BinaryFile.Trace(input, driver.TracingConfig)
// sanity check
if len(errs) > 0 {
for _, err := range errs {
t.Errorf("%s", err.Error())
}
t.FailNow()
}
//
if errs := driver.BinaryFile.Check(tr, driver.TracingConfig); len(errs) > 0 {
for _, err := range errs {
t.Errorf("%s", err.Message())
}
t.FailNow()
}
}
Loading
Loading