mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-09 20:27:58 -05:00
* feat(limits): unhardcode the keccak limits * limits(shomei): double the state limits * fix(rlpaddr): uses the right stamp column for rlpaddr * fix(ecpair): fix 1 invalid constraints and a bug in the assignment * log(plonk): logs which circuit is failing in plonk-in-wizard * log(projection): print a more informative message when a projection query fails * feat(csv): adds more options to FmtCSV * fix(mimc): removes a non-necessary constraint for mimc padding * fix(mimc): address the edge-case where the mimc data size is a multiple of 31 * fix(sha2): uses the correct selectors to extract the sha2 hashes * chores(makefile): dont recreate the zkevm.bin when linting or running the checker * chore(make): adds the bin/checker in the .PHONY * chores(cs): bump the constraints to rc7 * fix(arithmetization): fix invalid casting into a variable
253 lines
5.7 KiB
Go
253 lines
5.7 KiB
Go
// Package csvtraces provides a way to read and write traces in CSV format.
|
|
package csvtraces
|
|
|
|
import (
|
|
"encoding/csv"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/consensys/linea-monorepo/prover/maths/common/smartvectors"
|
|
"github.com/consensys/linea-monorepo/prover/maths/field"
|
|
"github.com/consensys/linea-monorepo/prover/protocol/ifaces"
|
|
"github.com/consensys/linea-monorepo/prover/protocol/wizard"
|
|
"github.com/consensys/linea-monorepo/prover/utils"
|
|
)
|
|
|
|
type cfg struct {
|
|
// The number of rows in the trace
|
|
nbRows int
|
|
skipPrePaddingZero bool
|
|
filterOn ifaces.Column
|
|
}
|
|
|
|
type Option func(*cfg) error
|
|
|
|
// WithNbRows sets the number of rows in the trace
|
|
func WithNbRows(nbRows int) Option {
|
|
return func(c *cfg) error {
|
|
c.nbRows = nbRows
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// SkipPrepaddingZero skips the zeroes at the beginning of the file
|
|
func SkipPrepaddingZero(c *cfg) error {
|
|
c.skipPrePaddingZero = true
|
|
return nil
|
|
}
|
|
|
|
// FilterOn sets the CSV printer to ignore rows where the provided filter
|
|
// column is zero.
|
|
func FilterOn(col ifaces.Column) Option {
|
|
return func(c *cfg) error {
|
|
c.filterOn = col
|
|
return nil
|
|
}
|
|
}
|
|
|
|
type CsvTrace struct {
|
|
mapped map[string][]field.Element
|
|
|
|
nbRows int
|
|
}
|
|
|
|
func MustOpenCsvFile(fName string) *CsvTrace {
|
|
|
|
f, err := os.Open(fName)
|
|
if err != nil {
|
|
utils.Panic("%v", err.Error())
|
|
}
|
|
defer f.Close()
|
|
|
|
ct, err := NewCsvTrace(f)
|
|
if err != nil {
|
|
utils.Panic("could not parse CSV: %v", err.Error())
|
|
}
|
|
|
|
return ct
|
|
}
|
|
|
|
// FmtCsv is a utility function that can be used in order to print a set of column
|
|
// in a csv format so that debugging and testcase generation are simpler.
|
|
func FmtCsv(w io.Writer, run *wizard.ProverRuntime, cols []ifaces.Column, options []Option) error {
|
|
|
|
var (
|
|
header = []string{}
|
|
assignment = [][]field.Element{}
|
|
cfg = cfg{}
|
|
foundNonZero = false
|
|
filterCol []field.Element
|
|
)
|
|
|
|
for _, op := range options {
|
|
op(&cfg)
|
|
}
|
|
|
|
for i := range cols {
|
|
header = append(header, string(cols[i].GetColID()))
|
|
assignment = append(assignment, cols[i].GetColAssignment(run).IntoRegVecSaveAlloc())
|
|
}
|
|
|
|
fmt.Fprintf(w, "%v\n", strings.Join(header, ","))
|
|
|
|
if cfg.filterOn != nil {
|
|
filterCol = cfg.filterOn.GetColAssignment(run).IntoRegVecSaveAlloc()
|
|
}
|
|
|
|
for r := range assignment[0] {
|
|
|
|
var (
|
|
fmtVals = []string{}
|
|
allZeroes = true
|
|
)
|
|
|
|
for c := range assignment {
|
|
|
|
if !assignment[c][r].IsZero() {
|
|
allZeroes = false
|
|
}
|
|
|
|
if assignment[c][r].IsUint64() {
|
|
fmtVals = append(fmtVals, assignment[c][r].String())
|
|
continue
|
|
}
|
|
|
|
fmtVals = append(fmtVals, "0x"+assignment[c][r].Text(16))
|
|
}
|
|
|
|
if !allZeroes {
|
|
foundNonZero = true
|
|
}
|
|
|
|
if filterCol != nil && filterCol[r].IsZero() {
|
|
continue
|
|
}
|
|
|
|
if !cfg.skipPrePaddingZero || !allZeroes || foundNonZero {
|
|
fmt.Fprintf(w, "%v\n", strings.Join(fmtVals, ","))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func NewCsvTrace(r io.Reader, opts ...Option) (*CsvTrace, error) {
|
|
cfg := &cfg{}
|
|
for _, opt := range opts {
|
|
if err := opt(cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
rr := csv.NewReader(r)
|
|
rr.FieldsPerRecord = 0
|
|
|
|
data := make(map[string][]field.Element)
|
|
header, err := rr.Read()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read header row: %w", err)
|
|
}
|
|
for _, h := range header {
|
|
data[h] = make([]field.Element, 0)
|
|
}
|
|
var nbRows int
|
|
for row, err := rr.Read(); err != io.EOF; row, err = rr.Read() {
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read row: %w", err)
|
|
}
|
|
for i, h := range header {
|
|
data[h] = append(data[h], field.NewFromString(row[i]))
|
|
}
|
|
nbRows++
|
|
}
|
|
if cfg.nbRows != 0 {
|
|
if cfg.nbRows < nbRows {
|
|
return nil, fmt.Errorf("invalid number of rows: %d", cfg.nbRows)
|
|
}
|
|
nbRows = cfg.nbRows
|
|
}
|
|
|
|
return &CsvTrace{mapped: data, nbRows: nbRows}, nil
|
|
}
|
|
|
|
func (c *CsvTrace) Get(name string) []field.Element {
|
|
val, ok := c.mapped[name]
|
|
if !ok {
|
|
utils.Panic("column not found %s", name)
|
|
}
|
|
return val
|
|
}
|
|
|
|
func (c *CsvTrace) GetCommit(b *wizard.Builder, name string) ifaces.Column {
|
|
if _, ok := c.mapped[name]; !ok {
|
|
utils.Panic("column not found %s", name)
|
|
}
|
|
length := utils.NextPowerOfTwo(c.nbRows)
|
|
col := b.RegisterCommit(ifaces.ColID(name), length)
|
|
return col
|
|
}
|
|
|
|
func (c *CsvTrace) Assign(run *wizard.ProverRuntime, names ...string) {
|
|
length := utils.NextPowerOfTwo(c.nbRows)
|
|
for _, k := range names {
|
|
if v, ok := c.mapped[k]; ok {
|
|
sv := smartvectors.RightZeroPadded(v, length)
|
|
run.AssignColumn(ifaces.ColID(k), sv)
|
|
} else {
|
|
utils.Panic("column not found %s", k)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *CsvTrace) CheckAssignment(run *wizard.ProverRuntime, names ...string) {
|
|
for _, name := range names {
|
|
c.checkAssignment(run, name)
|
|
}
|
|
}
|
|
|
|
func (c *CsvTrace) checkAssignment(run *wizard.ProverRuntime, name string) {
|
|
colId := ifaces.ColID(name)
|
|
assigned := run.Spec.Columns.GetHandle(colId)
|
|
c.CheckAssignmentColumn(run, name, assigned)
|
|
|
|
}
|
|
|
|
func (c *CsvTrace) CheckAssignmentColumn(run *wizard.ProverRuntime, name string, col ifaces.Column) {
|
|
|
|
var (
|
|
stored, ok = c.mapped[name]
|
|
assigned = col.GetColAssignment(run)
|
|
fullLength = utils.NextPowerOfTwo(c.nbRows)
|
|
)
|
|
|
|
if !ok {
|
|
utils.Panic("column not found in CSV: %s", name)
|
|
}
|
|
|
|
if assigned.Len() < fullLength {
|
|
utils.Panic("column %s has not been assigned with the expected length, found %v in CSV and %v in wizard", name, fullLength, assigned.Len())
|
|
}
|
|
|
|
vec := assigned.IntoRegVecSaveAlloc()
|
|
for i := 0; i < c.nbRows; i++ {
|
|
if vec[i].Cmp(&stored[i]) != 0 {
|
|
utils.Panic("column %s has not been assigned correctly: row %d CSV=%s got Wizard=%s", name, i, stored[i].String(), vec[i].String())
|
|
}
|
|
}
|
|
|
|
for i := c.nbRows; i < assigned.Len(); i++ {
|
|
if !vec[i].IsZero() {
|
|
utils.Panic("column %s is not properly zero-padded", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *CsvTrace) Len() int {
|
|
return c.nbRows
|
|
}
|
|
|
|
func (c *CsvTrace) LenPadded() int {
|
|
return utils.NextPowerOfTwo(c.nbRows)
|
|
}
|