diff --git a/pkg/binfile/constraint_set.go b/pkg/binfile/constraint_set.go index a17f04c..6692502 100644 --- a/pkg/binfile/constraint_set.go +++ b/pkg/binfile/constraint_set.go @@ -38,7 +38,7 @@ type column struct { // information about the length of this column (e.g. its a // multiple of two). This seems only relevant for computed // columns. - IntrinsicSizeFactor string `json:"intrinsic_size_factor"` + IntrinsicSizeFactor uint `json:"intrinsic_size_factor"` // Indicates this is a computed column. For binfiles being // compiled without expansion, this should always be false. Computed bool @@ -82,6 +82,10 @@ type register struct { // the original binfile format. Instead, this field is determined from // parsing the binfile format. MustProve bool + // LengthMultiplier indicates the length multiplier for this column. This + // must be a factor of the number of rows in the column. For example, a + // column with length multiplier of 2 must have an even number of rows, etc. + LengthMultiplier uint `json:"length_multiplier"` } type columnSet struct { @@ -168,8 +172,7 @@ func allocateRegisters(cs *constraintSet, schema *hir.Schema) map[uint]uint { if !c.Computed { handle := asHandle(c.Handle) mid := registerModule(schema, handle.module) - // NOTE: assumption here that length multiplier is always one. - ctx := trace.NewContext(mid, 1) + ctx := trace.NewContext(mid, c.LengthMultiplier) col_type := c.Type.toHir() // Add column for this cid := schema.AddDataColumn(ctx, handle.column, col_type) diff --git a/pkg/schema/builder.go b/pkg/schema/builder.go index 0e922c2..58436e1 100644 --- a/pkg/schema/builder.go +++ b/pkg/schema/builder.go @@ -96,8 +96,8 @@ func (tb TraceBuilder) Build(columns []trace.RawColumn) (trace.Trace, []error) { // A column key is used as a key for the column map type columnKey struct { - context trace.Context - column string + module uint + column string } func (tb TraceBuilder) initialiseTrace(cols []trace.RawColumn) (*trace.ArrayTrace, []error) { @@ -150,7 +150,7 @@ func (tb TraceBuilder) initialiseTraceColumns() ([]trace.ArrayColumn, map[column for i, iter := uint(0), tb.schema.Columns(); iter.HasNext(); i++ { c := iter.Next() // Construct an appropriate key for this column - colkey := columnKey{c.Context(), c.Name()} + colkey := columnKey{c.Context().Module(), c.Name()} // Initially column data and padding are nil. In some cases, we will // populate this information from the cols array. However, in other // cases, it will need to be populated during trace expansion. @@ -180,12 +180,8 @@ func fillTraceColumns(modmap map[string]uint, colmap map[columnKey]uint, if !ok { errs = append(errs, fmt.Errorf("unknown module '%s' in trace", c.Module)) } else { - // We assume (for now) that user-provided columns always have a length - // multiplier of 1. In general, this will be true. However, in situations - // where we are importing expanded traces, then this might not be true. - context := trace.NewContext(mid, 1) // Determine enclosiong module height - cid, ok := colmap[columnKey{context, c.Name}] + cid, ok := colmap[columnKey{mid, c.Name}] // More sanity checks if !ok { errs = append(errs, fmt.Errorf("unknown column '%s' in trace", c.QualifiedName())) diff --git a/pkg/trace/array_trace.go b/pkg/trace/array_trace.go index 0313469..3716eb9 100644 --- a/pkg/trace/array_trace.go +++ b/pkg/trace/array_trace.go @@ -59,14 +59,14 @@ func (p *ArrayTrace) FillColumn(cid uint, data util.FrArray, padding fr.Element) // Sanity check this column has not already been filled. if data.Len()%multiplier != 0 { colname := QualifiedColumnName(mod.name, col.name) - panic(fmt.Sprintf("computed column %s has invalid length multiplier (%d indivisible by %d)", + panic(fmt.Sprintf("column %s has invalid length multiplier (%d indivisible by %d)", colname, data.Len(), multiplier)) } else if mod.height == math.MaxUint { // Initialise column height mod.height = data.Len() / col.context.multiplier } else if data.Len() != p.Height(col.Context()) { colname := QualifiedColumnName(mod.name, col.name) - panic(fmt.Sprintf("computed column %s has invalid height (%d but expected %d)", colname, data.Len(), mod.height)) + panic(fmt.Sprintf("column %s has invalid height (%d but expected %d)", colname, data.Len(), mod.height*multiplier)) } // Fill the column col.fill(data, padding) diff --git a/pkg/trace/context.go b/pkg/trace/context.go index ad94a16..8fc9051 100644 --- a/pkg/trace/context.go +++ b/pkg/trace/context.go @@ -63,7 +63,7 @@ func (p Context) Module() uint { panic("void context has no module") } - panic("conflicted context has no module") + panic("conflicted context") } // LengthMultiplier returns the length multiplier for this context. Note,