Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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.1
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.1 h1:PXDUBvk8AzhvWowHLWBEAfUQcV1/aZgWIqD6eMpXmDg=
github.com/consensys/gnark-crypto v0.20.1/go.mod h1:RBWrSgy+IDbGR69RRV313th3M/aZU1ubk2om+qHuTSc=
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
23 changes: 18 additions & 5 deletions prover-ray/zkcdriver/assignment.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package zkcdriver

import (
"fmt"
"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,19 +21,30 @@ 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) {
for id := start; id < stop; id++ {

fmt.Printf("zkcdriver: AssignFromTrace: processing column %d : annotation %v\n", id, run.System.Annotations)
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated

var (
sys = run.System
columnIDMap = sys.Annotations[corsetColumnMapAnnotationKey].(map[string]wiop.ObjectID)
Expand All @@ -41,7 +54,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 +87,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 @@ -2,6 +2,7 @@ package zkcdriver

import (
"fmt"
"log"
"sort"

"github.com/consensys/linea-monorepo/prover-ray/maths/koalabear/field"
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).
log.Panic("zkcdriver: add support for native modules!")
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated
}

// 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
3 changes: 1 addition & 2 deletions prover-ray/zkcdriver/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package zkcdriver_test
import (
"testing"

"github.com/consensys/go-corset/pkg/ir/mir"
Comment thread
cursor[bot] marked this conversation as resolved.
"github.com/consensys/linea-monorepo/prover-ray/utils/files"
"github.com/consensys/linea-monorepo/prover-ray/wiop"
"github.com/consensys/linea-monorepo/prover-ray/zkcdriver"
Expand All @@ -18,7 +17,7 @@ func TestZkEVMDefinition(t *testing.T) {
sys.NewRound()
_ = zkcdriver.NewZkCDriver(
sys,
zkcdriver.Settings{OptimisationLevel: &mir.DEFAULT_OPTIMISATION_LEVEL},
zkcdriver.Settings{},
files.MustRead("./testdata/zkevm.bin"),
)
}
78 changes: 78 additions & 0 deletions prover-ray/zkcdriver/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
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/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)
// 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