Documentation
¶
Overview ¶
Copyright Consensys Software Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Index ¶
- func BigNumber[T any, E Expr[T, E]](c *big.Int) E
- func False[T any, E Expr[T, E]]() E
- func If[T any, E Expr[T, E]](condition E, trueBranch E) E
- func IfElse[T any, E Expr[T, E]](condition E, trueBranch E, falseBranch E) E
- func Number[T any, E Expr[T, E]](c uint) E
- func Or[T any, E Expr[T, E]](first E, rest ...E) E
- func Product[T any, E Expr[T, E]](exprs ...E) E
- func ReadRegister[T any, E Expr[T, E]](reg dfa.BranchId, reader RegisterReader[E]) E
- func Sum[T any, E Expr[T, E]](exprs []E) E
- func TranslateBranchCondition[T any, E Expr[T, E]](p dfa.BranchCondition, reader RegisterReader[E]) E
- func True[T any, E Expr[T, E]]() E
- func Variable[T any, E Expr[T, E]](id T, bitwidth uint, shift int) E
- type Compiler
- type Element
- type Expr
- type Framing
- type FunctionMapping
- type LegacyMultiLineFraming
- type MicroComponent
- type MicroFunction
- type MicroProgram
- type MirExpr
- func (p MirExpr[F]) Add(exprs ...MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) And(exprs ...MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) AsLogical() mir.LogicalTerm[F]
- func (p MirExpr[F]) BigInt(number big.Int) MirExpr[F]
- func (p MirExpr[F]) Bool(val bool) MirExpr[F]
- func (p MirExpr[F]) Equals(rhs MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) Multiply(exprs ...MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) NotEquals(rhs MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) Or(exprs ...MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) String(func(register.Id) string) string
- func (p MirExpr[F]) Then(trueBranch MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) ThenElse(trueBranch MirExpr[F], falseBranch MirExpr[F]) MirExpr[F]
- func (p MirExpr[F]) Variable(index register.Id, bitwidth uint, shift int) MirExpr[F]
- type MirModule
- func (p MirModule[F]) Initialise(mid uint, fn MicroComponent) MirModule[F]
- func (p MirModule[F]) NewAssignment(assignment schema.Assignment[F])
- func (p MirModule[F]) NewColumn(kind register.Type, name string, bitwidth uint, padding big.Int) register.Id
- func (p MirModule[F]) NewConstraint(name string, domain util.Option[int], constraint MirExpr[F])
- func (p MirModule[F]) NewLookup(name string, from []register.Id, target MirModule[F], to []register.Id, ...)
- func (p MirModule[F]) NewUnusedColumn() register.Id
- func (p MirModule[F]) String() string
- type Module
- type ModuleBuilder
- type MultiLineFraming
- type OneLineFraming
- type RegisterReader
- type StateTranslator
- func (p *StateTranslator[F, T, E, M]) ReadRegister(regId io.RegisterId) E
- func (p *StateTranslator[F, T, E, M]) ReadRegisters(sources []io.RegisterId) []E
- func (p *StateTranslator[F, T, E, M]) WriteAndShiftRegisters(targets []io.RegisterId) []E
- func (p *StateTranslator[F, T, E, M]) WriteRegister(dst io.RegisterId) E
- func (p *StateTranslator[F, T, E, M]) WriteRegisters(targets []io.RegisterId) []E
- type Translator
- func (p *Translator[F, T, E, M]) ReadRegister(regId io.RegisterId, forwarding bool) E
- func (p *Translator[F, T, E, M]) Register(reg io.RegisterId) io.Register
- func (p *Translator[F, T, E, M]) RegisterWidths(regs ...io.RegisterId) []uint
- func (p *Translator[F, T, E, M]) Translate(pc uint, insn micro.Instruction) E
- func (p *Translator[F, T, E, M]) WithConstancyConstraints(writes dfa.Writes, branchTable dfa.Result[dfa.Branch], insn micro.Instruction, ...) E
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ReadRegister ¶
func ReadRegister[T any, E Expr[T, E]](reg dfa.BranchId, reader RegisterReader[E]) E
ReadRegister constructs a suitable accessor for referring to a given register. This applies forwarding as appropriate.
func TranslateBranchCondition ¶
func TranslateBranchCondition[T any, E Expr[T, E]](p dfa.BranchCondition, reader RegisterReader[E]) E
TranslateBranchCondition translates a given branch condition within the context of a given state reader.
Types ¶
type Compiler ¶
type Compiler[F Element[F], T any, E Expr[T, E], M Module[F, T, E, M]] struct { // contains filtered or unexported fields }
Compiler packages up everything needed to compile a given assembly down into an HIR schema. Observe that the compiler may fail if the assembly files are malformed in some way (e.g. fail type checking).
func NewCompiler ¶
NewCompiler constructs a new compiler
func (*Compiler[F, T, E, M]) Compile ¶
func (p *Compiler[F, T, E, M]) Compile(program MicroProgram)
Compile a given set of micro functions
type Expr ¶
type Expr[T, E any] interface { // Add constructs a sum between this expression and zero or more Add(exprs ...E) E // And constructs a conjunction between this expression and zero or more // expressions. And(...E) E // Bool constructs a logical truth or falsehood Bool(bool) E // Equals constructs an equality between two expressions. Equals(rhs E) E // Then constructs an implication between two expressions. Then(trueBranch E) E // ThenElse constructs an if-then-else expression with this expression // acting as the condition. ThenElse(trueBranch E, falseBranch E) E // Multiply constructs a product between this expression and zero or more // expressions. Multiply(...E) E // NotEquals constructs a non-equality between two expressions. NotEquals(rhs E) E // Number constructs a constant expression. BigInt(number big.Int) E // Or constructs a disjunction between this expression and zero or more // expressions. Or(...E) E // Variable constructs a variable with a given shift. Variable(name T, bitwidth uint, shift int) E // String returns a suitable string representation String(func(T) string) string }
Expr provides an abstraction over expressions in the constraint language. Using an abstraction, rather than concrete constraint expressions directly, makes it relatively easier to support multiple target languages.
type Framing ¶
type Framing[T any, E Expr[T, E]] interface { // Guard provides a suitable guard for the instruction at a given PC offset. // This is optional as some forms of framing don't require it. Guard(pc uint) E // Goto indicates the current instruction is jumping to the given PC value. Goto(pc uint) E // Return provides a suitable transition to the next frame. Return() E }
Framing is used to manage additional registers required to ensure soundness. In particular, framinging applies to multi-line functions as these require a program counter, and various control lines to manage padding and non-terminal states.
func NewAtomicFraming ¶
NewAtomicFraming constructs a suitable framing for a one-line instruction.
func NewLegacyMultiLineFraming ¶ added in v1.2.21
func NewLegacyMultiLineFraming[T any, E Expr[T, E]](pc T, pcWidth uint, ret T, retWidth uint) Framing[T, E]
NewLegacyMultiLineFraming is a legacy constructor used only by zkasm, not by zkc.
func NewMultiLineFraming ¶
func NewMultiLineFraming[T any, E Expr[T, E]](pc T, pcWidth uint, ret T, retWidth uint, selectors []T) Framing[T, E]
NewMultiLineFraming constructs framing for a multi-line function. It assumes the caller has allocated $ret, PC and IS_PC_<k> selector registers and passes their ids here.
type FunctionMapping ¶
type FunctionMapping[T any] struct { // contains filtered or unexported fields }
FunctionMapping provides information regarding the mapping of a assembly-level component (e.g. a function) to the corresponding columns in the underlying constraint system.
func (*FunctionMapping[T]) Bus ¶
func (p *FunctionMapping[T]) Bus() []T
Bus returns the set of input/output columns which represent the "Bus" for this component.
func (*FunctionMapping[T]) ColumnsOf ¶
func (p *FunctionMapping[T]) ColumnsOf(registers ...io.RegisterId) []T
ColumnsOf returns the underlying column identifiers for a given set of zero or more registers.
func (*FunctionMapping[T]) ProgramCounter ¶
func (p *FunctionMapping[T]) ProgramCounter() T
ProgramCounter returns the corresponding column
func (*FunctionMapping[T]) ReturnLine ¶
func (p *FunctionMapping[T]) ReturnLine() T
ReturnLine returns the corresponding column
type LegacyMultiLineFraming ¶ added in v1.2.21
type LegacyMultiLineFraming[T any, E Expr[T, E]] struct { // contains filtered or unexported fields }
LegacyMultiLineFraming provides suitable control lines for multi-line functions, guarding each instruction with an equality on the program counter.
func (*LegacyMultiLineFraming[T, E]) Goto ¶ added in v1.2.21
func (p *LegacyMultiLineFraming[T, E]) Goto(pc uint) E
Goto implementation for Framing interface.
func (*LegacyMultiLineFraming[T, E]) Guard ¶ added in v1.2.21
func (p *LegacyMultiLineFraming[T, E]) Guard(pc uint) E
Guard implementation for Framing interface.
func (*LegacyMultiLineFraming[T, E]) Return ¶ added in v1.2.21
func (p *LegacyMultiLineFraming[T, E]) Return() E
Return implementation for Framing interface.
type MicroComponent ¶
type MicroComponent = io.Component[micro.Instruction]
MicroComponent is a component whose instructions (if applicable) are themselves micro instructions. A micro function represents the lowest representation of a function, where each instruction is made up of microcodes.
type MicroFunction ¶
type MicroFunction = io.Function[micro.Instruction]
MicroFunction is a function composed entirely of micro instructions.
type MicroProgram ¶
type MicroProgram = io.Program[micro.Instruction]
MicroProgram is a program made up from micro- (and external) functions.
type MirExpr ¶
MirExpr is a wrapper around a corset expression which provides the necessary interface.
func (MirExpr[F]) And ¶
And constructs a conjunction between this expression and zero or more expressions.
func (MirExpr[F]) AsLogical ¶
func (p MirExpr[F]) AsLogical() mir.LogicalTerm[F]
AsLogical extracts a logical constraint from this expression.
func (MirExpr[F]) Multiply ¶
Multiply constructs a product between this expression and zero or more expressions.
func (MirExpr[F]) Or ¶
Or constructs a disjunction between this expression and zero or more expressions.
type MirModule ¶
type MirModule[F field.Element[F]] struct { Module ModuleBuilder[F] }
MirModule provides a wrapper around a corset-level module declaration.
func (MirModule[F]) Initialise ¶
func (p MirModule[F]) Initialise(mid uint, fn MicroComponent) MirModule[F]
Initialise this module
func (MirModule[F]) NewAssignment ¶
func (p MirModule[F]) NewAssignment(assignment schema.Assignment[F])
NewAssignment adds a new assignment to this module.
func (MirModule[F]) NewColumn ¶
func (p MirModule[F]) NewColumn(kind register.Type, name string, bitwidth uint, padding big.Int, ) register.Id
NewColumn constructs a new column of the given name and bitwidth within this module.
func (MirModule[F]) NewConstraint ¶
NewConstraint constructs a new vanishing constraint with the given name within this module.
func (MirModule[F]) NewLookup ¶
func (p MirModule[F]) NewLookup(name string, from []register.Id, target MirModule[F], to []register.Id, enable util.Option[register.Id])
NewLookup constructs a new lookup constraint
func (MirModule[F]) NewUnusedColumn ¶
NewUnusedColumn constructs an empty (i.e. unused) column identifier.
type Module ¶
type Module[F field.Element[F], T any, E Expr[T, E], M any] interface { // SetName sets the name of this module. Initialise(mid uint, fn MicroComponent) M // NewAssignment adds a new assignment to this module. NewAssignment(assignment schema.Assignment[F]) // NewColumn constructs a new column of the given name and bitwidth within // this module. NewColumn(kind register.Type, name string, bitwidth uint, padding big.Int) T // NewUnusedColumn constructs an empty (i.e. unused) column identifier. NewUnusedColumn() T // NewConstraint constructs a new vanishing constraint with the given name // within this module. An optional "domain" can be given which determines // whether or not this is a "local" or "global" constraint. Specifically, a // local constraint applies only on one row whereas a global constraints // applies on all rows. The domain (if supplied) determines the row where a // local constraint applies, with negative values being offset from the last // row. Thus, a domain value of 0 (reps -1) represents the first (resp. // last) row of the module. NewConstraint(name string, domain util.Option[int], expr E) // NewLookup constructs a new lookup constraint NewLookup(name string, from []T, target M, to []T, enable util.Option[T]) // String returns an appropriately formatted representation of the module. String() string }
Module provides an abstraction for modules in the underlying constraint system.
type ModuleBuilder ¶
type ModuleBuilder[F field.Element[F]] = ir.ModuleBuilder[F, mir.Constraint[F], mir.Term[F]]
ModuleBuilder is used within this translator for building the various modules which are contained within the mixed MIR schema.
type MultiLineFraming ¶
type MultiLineFraming[T any, E Expr[T, E]] struct { LegacyMultiLineFraming[T, E] // contains filtered or unexported fields }
MultiLineFraming provides suitable control lines for multi-line functions, guarding each instruction with a dedicated boolean selector register. It reuses the legacy framing for Goto/Return (which act on the program counter and return line) and overrides only the per-instruction Guard.
func (*MultiLineFraming[T, E]) Guard ¶
func (p *MultiLineFraming[T, E]) Guard(pc uint) E
Guard implementation for Framing interface. Guards directly on the selector for this instruction. Since the selector is a width-1 register, the resulting condition lowers to the bare column with no inverse.
type OneLineFraming ¶
OneLineFraming is suitable for one-line functions, as these require no control lines.
func (*OneLineFraming[T, E]) Goto ¶
func (p *OneLineFraming[T, E]) Goto(pc uint) E
Goto implementation for Framing interface.
func (*OneLineFraming[T, E]) Guard ¶
func (p *OneLineFraming[T, E]) Guard(pc uint) E
Guard implementation for Framing interface.
func (*OneLineFraming[T, E]) Return ¶
func (p *OneLineFraming[T, E]) Return() E
Return implementation for Framing interface.
type RegisterReader ¶
type RegisterReader[E any] interface { // Register returns information about a given register Register(io.RegisterId) io.Register // RegisterWidths returns the bitwidth of a given set of registers. RegisterWidths(reg ...io.RegisterId) []uint // ReadRegister constructs a suitable accessor for referring to a given register. // This applies forwarding as appropriate. ReadRegister(reg io.RegisterId, forwarding bool) E }
RegisterReader is a simplified view of a translator which is suitable for reading registers only.
type StateTranslator ¶
type StateTranslator[F field.Element[F], T any, E Expr[T, E], M Module[F, T, E, M]] struct { // contains filtered or unexported fields }
StateTranslator packages up key information regarding how an individual state of the machine is compiled down to the lower level.
func (*StateTranslator[F, T, E, M]) ReadRegister ¶
func (p *StateTranslator[F, T, E, M]) ReadRegister(regId io.RegisterId) E
ReadRegister constructs a suitable accessor for referring to a given register. This applies forwarding as appropriate.
func (*StateTranslator[F, T, E, M]) ReadRegisters ¶
func (p *StateTranslator[F, T, E, M]) ReadRegisters(sources []io.RegisterId) []E
ReadRegisters constructs appropriate column accesses for a given set of registers. When appropriate, forwarding will be applied automatically.
func (*StateTranslator[F, T, E, M]) WriteAndShiftRegisters ¶
func (p *StateTranslator[F, T, E, M]) WriteAndShiftRegisters(targets []io.RegisterId) []E
WriteAndShiftRegisters constructs suitable accessors for the those registers written by a given microinstruction, and also shifts them (i.e. so they can be combined in a sum). This activates forwarding for those registers for all states after this, and returns suitable expressions for the assignment.
func (*StateTranslator[F, T, E, M]) WriteRegister ¶
func (p *StateTranslator[F, T, E, M]) WriteRegister(dst io.RegisterId) E
WriteRegister constructs a suitable accessors for a register written by a given microinstruction. This activates forwarding for that register for all states after this, and returns a suitable expression for the assignment.
func (*StateTranslator[F, T, E, M]) WriteRegisters ¶
func (p *StateTranslator[F, T, E, M]) WriteRegisters(targets []io.RegisterId) []E
WriteRegisters constructs suitable accessors for the those registers written by a given microinstruction. This activates forwarding for those registers for all states after this, and returns suitable expressions for the assignment.
type Translator ¶
type Translator[F field.Element[F], T any, E Expr[T, E], M Module[F, T, E, M]] struct { // Framining identifies any required control lines. Framing Framing[T, E] // Registers of the given machine Registers []io.Register // Mapping from registers to column IDs in the underlying constraint system. Columns []T // contains filtered or unexported fields }
Translator encapsulates general information related to the mapping from instructions down to constraints.
func (*Translator[F, T, E, M]) ReadRegister ¶
func (p *Translator[F, T, E, M]) ReadRegister(regId io.RegisterId, forwarding bool) E
ReadRegister constructs a suitable accessor for referring to a given register. This applies forwarding as appropriate.
func (*Translator[F, T, E, M]) Register ¶
func (p *Translator[F, T, E, M]) Register(reg io.RegisterId) io.Register
Register implementation for RegisterReader interface
func (*Translator[F, T, E, M]) RegisterWidths ¶
func (p *Translator[F, T, E, M]) RegisterWidths(regs ...io.RegisterId) []uint
RegisterWidths implementation for RegisterReader interface
func (*Translator[F, T, E, M]) Translate ¶
func (p *Translator[F, T, E, M]) Translate(pc uint, insn micro.Instruction) E
Translate a micro instruction at a given Program Counter value into a given constraint.
func (*Translator[F, T, E, M]) WithConstancyConstraints ¶
func (p *Translator[F, T, E, M]) WithConstancyConstraints(writes dfa.Writes, branchTable dfa.Result[dfa.Branch], insn micro.Instruction, condition E) E
WithConstancyConstraints adds constancy constraints for all registers which are either not mutated at all by an instruction, or are sometimes mutated by an instruction. Constancy constraints are required when the value of a register should be copied from the previous state into this state (i.e. because it was not changed by this instruction and, hence, must retain its original value).
A key challenge lies with registers that are sometimes assigned by the instruction, and sometimes not assigned (i.e. maybe but not definitely assigned). To resolve this we first determine the conditions under which they are assigned, and negate this to determine the conditions under which they are not assigned.
NOTE: it is possible to further optimise this process by taking into account which registers are actually used (i.e. live) after this instruction.