vm

package
v1.2.23 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

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

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

Constants

View Source
const (
	// OP_ADD integer addition.
	OP_ADD = bytecode.OP_ADD
	// OP_SUB integer subtraction.
	OP_SUB = bytecode.OP_SUB
	// OP_MUL integer multiplication.
	OP_MUL = bytecode.OP_MUL
	// OP_AND bitwise conjunction.
	OP_AND = bytecode.OP_AND
	// OP_OR bitwise disjunction.
	OP_OR = bytecode.OP_OR
	// OP_XOR bitwise exclusive-or.
	OP_XOR = bytecode.OP_XOR
	// OP_NOT bitwise negation.
	OP_NOT = bytecode.OP_NOT
	// OP_SHL logical shift left.
	OP_SHL = bytecode.OP_SHL
	// OP_SHR logical shift right.
	OP_SHR = bytecode.OP_SHR
	// OP_ADDMOD_P addition modulo the field prime.
	OP_ADDMOD_P = bytecode.OP_ADDMOD_P
	// OP_SUBMOD_P subtraction modulo the field prime.
	OP_SUBMOD_P = bytecode.OP_SUBMOD_P
	// OP_MULMOD_P multiplication modulo the field prime.
	OP_MULMOD_P = bytecode.OP_MULMOD_P
	// DIV_HINT division hint operation.
	DIV_HINT = bytecode.DIV_HINT
)

Operation constants (mirroring bytecode.OP_*).

Variables

View Source
var (
	// BYTECODE_FUNCTION is a safe function implemented by bytecode.
	BYTECODE_FUNCTION = descriptor.BYTECODE_FUNCTION
	// NATIVE_FUNCTION is a safe function backed by a native circuit.
	NATIVE_FUNCTION = descriptor.NATIVE_FUNCTION
	// UNSAFE_ARGS_FUNCTION is a bytecode function which may receive undefined arguments.
	UNSAFE_ARGS_FUNCTION = descriptor.UNSAFE_ARGS_FUNCTION
	// NATIVE_UNSAFE_ARGS_FUNCTION is a native function which may receive undefined arguments.
	NATIVE_UNSAFE_ARGS_FUNCTION = descriptor.NATIVE_UNSAFE_ARGS_FUNCTION
)

Function kinds, re-exported for use with NewBytecodeFunction.

View Source
var (
	// PUBLIC_STATIC_MEMORY is a public static (compile-time initialised) read-only memory.
	PUBLIC_STATIC_MEMORY = descriptor.PUBLIC_STATIC_MEMORY
	// PRIVATE_STATIC_MEMORY is a private static (compile-time initialised) read-only memory.
	PRIVATE_STATIC_MEMORY = descriptor.PRIVATE_STATIC_MEMORY
	// PUBLIC_READ_ONLY_MEMORY is a public read-only memory.
	PUBLIC_READ_ONLY_MEMORY = descriptor.PUBLIC_READ_ONLY_MEMORY
	// PRIVATE_READ_ONLY_MEMORY is a private read-only memory.
	PRIVATE_READ_ONLY_MEMORY = descriptor.PRIVATE_READ_ONLY_MEMORY
	// PUBLIC_WRITE_ONCE_MEMORY is a public write-once memory.
	PUBLIC_WRITE_ONCE_MEMORY = descriptor.PUBLIC_WRITE_ONCE_MEMORY
	// PRIVATE_WRITE_ONCE_MEMORY is a private write-once memory.
	PRIVATE_WRITE_ONCE_MEMORY = descriptor.PRIVATE_WRITE_ONCE_MEMORY
	// READWRITE_MEMORY is a (private) random-access read-write memory.
	READWRITE_MEMORY = descriptor.READWRITE_MEMORY
	// PAGED_READWRITE_MEMORY is a (private) paged random-access read-write memory.
	PAGED_READWRITE_MEMORY = descriptor.PAGED_READWRITE_MEMORY
)

Memory kinds, re-exported for use with NewBytecodeMemory.

View Source
var WORD_UINT128 = WordConfig{Name: "Uint128", BandWidth: 128, RegisterWidth: 64}

WORD_UINT128 provides metadata about the Uint128 word type.

View Source
var WORD_UINT64 = WordConfig{Name: "Uint64", BandWidth: 64, RegisterWidth: 32}

WORD_UINT64 provides metadata about the Uint64 word type.

Functions

func BootAndDebug added in v1.2.21

func BootAndDebug[W Word[W]](program Program[W], in map[string][]byte, observer func(State[W])) []error

BootAndDebug boots the given program on the given inputs and executes it to completion using the bytecode interpreter, invoking observer once for each executed trace line (bytecode vector) with the machine State at that point (see State, which carries the executing function id, program counter and register values). This is the execution primitive underlying the `zkc debug` command: it uses the interpreter's breakpoint facility (enabled by running in tracing mode) so that a breakpoint fires as each vector completes.

func BootAndExecute

func BootAndExecute[W Word[W], M Core[W]](m M, input map[string][]byte, n uint,
) (output map[string][]byte, errs []error)

BootAndExecute executes the program embodied by these constraints in chunks of n steps at a time, producing any outputs arising. Execution is faster than trace because it does not record any internal information about the trace --- it simply extracts the outputs at the end.

func BootAndTrace added in v1.2.21

func BootAndTrace[W Word[W], F field.Element[F]](
	program Program[W], in map[string][]byte, n uint, processor TraceProcessor[W, F],
) (rtrace.Trace[F], map[string][]byte, []error)

BootAndTrace generates a suitable trace from the given inputs for the contraints embodied in this file. This can return one (or more) errors if, for example, the input is malformed (e.g. is missing expected fields and/or contains unexpected fields).

func Const64

func Const64[W Word[W]](val uint64) W

Const64 initialises a given word with a 64bit value. This will panic if the given value exceeds the available bandwidth of the word in question.

func DecodeBytes

func DecodeBytes[W Word[W]](bytes []byte, geometry descriptor.Memory[W]) []W

DecodeBytes decodes the given set of bytes as big integer values according to the given register type(s). Observe that values are assumed to be packed tightly (i.e. without any padding). Consider the following input byte array:

| 00 | 01 | 02 | 03 | +------+------+------+------+ | 0x31 | 0xf0 | 0x0e | 0x1d |

Then, decoding this into a u4 array will produce the following:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +-----+-----+-----+-----+-----+-----+-----+-----+ | 0x3 | 0x1 | 0xf | 0x0 | 0x0 | 0xe | 0x1 | 0xd |

If the input array is not a multiple of the bitwidth

func DecodeInputs

func DecodeInputs[W Word[W], C Core[W]](m C, input map[string][]byte) (map[string][]W, []error)

DecodeInputs configures a given set of input bytes appropriately for the given machine. If there are unknown or conflicting inputs, then errors are returned.

func DecodeInputsOutputs

func DecodeInputsOutputs[W Word[W]](program descriptor.Program[W], data map[string][]byte,
) (inputs, outputs map[string][]W, errs []error)

DecodeInputsOutputs decodes given set of input and output bytes appropriately for the given machine. If there are unknown or conflicting inputs, then errors are returned.

func DecodeUnsignedInt

func DecodeUnsignedInt(bitwidth uint, reader *bit.Reader, buffer []byte) ([]big.Int, []byte)

DecodeUnsignedInt decodes the given set of bytes as big integer values according to the given register type(s). Observe that values are assumed to be packed tightly (i.e. without any padding). Consider the following input byte array:

| 00 | 01 | 02 | 03 | +------+------+------+------+ | 0x31 | 0xf0 | 0x0e | 0x1d |

Then, decoding this into a u4 array will produce the following:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +-----+-----+-----+-----+-----+-----+-----+-----+ | 0x3 | 0x1 | 0xf | 0x0 | 0x0 | 0xe | 0x1 | 0xd |

If the input array is not a multiple of the bitwidth

func EncodeBytes

func EncodeBytes[W Word[W]](values []W, geometry descriptor.Memory[W]) []byte

EncodeBytes encodes the given set of word values as packed bytes according to the given registers type(s). This is the inverse of DecodeAll. Consider the following input array of u4 values:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +-----+-----+-----+-----+-----+-----+-----+-----+ | 0x3 | 0x1 | 0xf | 0x0 | 0x0 | 0xe | 0x1 | 0xd |

Then, encoding this as a u4 array will produce the following bytes:

| 00 | 01 | 02 | 03 | +------+------+------+------+ | 0x31 | 0xf0 | 0x0e | 0x1d |

func EncodeOutputs

func EncodeOutputs[W Word[W], M Core[W]](m M) map[string][]byte

EncodeOutputs extract the output from a given machine and encodes it into byte arrays.

func EncodeUnsignedInt

func EncodeUnsignedInt(bitwidth uint, v *big.Int, buf []byte)

EncodeUnsignedInt encodes the given big integer as packed bytes according to the given bitwidths. This is the inverse of DecodeUnsignedInt.

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +-----+-----+-----+-----+-----+-----+-----+-----+ | 0x3 | 0x1 | 0xf | 0x0 | 0x0 | 0xe | 0x1 | 0xd |

Then, encoding this as a u4 array will produce the following bytes:

| 00 | 01 | 02 | 03 | +------+------+------+------+ | 0x31 | 0xf0 | 0x0e | 0x1d |

func ExecuteAll

func ExecuteAll[W Word[W], M Core[W]](machine M, n uint) (uint, error)

ExecuteAll executes a given machine to completion in chunks of n steps, returning the number of steps executed and/or any error arising.

func FilterInputs added in v1.2.21

func FilterInputs[W Word[W], T any](p Program[W], input map[string][]T) map[string][]T

FilterInputs restricts the given set of (parsed) inputs to the program's declared input memories.

func GenerateGo

func GenerateGo(program Program[Uint], cfg GoGenConfig) (string, error)

GenerateGo compiles a bytecode program into native Go source: the "fast execution mode" alternative to interpreting the program. Where the bytecode interpreter builds a decode-dispatch loop, this emits plain Go the compiler can optimise — and it consumes the program over Uint (the same program the reference executor interprets), so the generated semantics mirror the reference executor, with no register splitting or word narrowing in the way.

The result exposes Run(inputs) (outputs, error); with cfg.Package == "main" (the default) a JSON stdin/stdout harness is appended, so the artefact can be compiled and run as a subprocess for differential testing and benchmarking.

func IsSubtractWithBorrow added in v1.2.22

func IsSubtractWithBorrow[W word.Word[W]](code BytecodeArith[W], env descriptor.RegisterMap[W]) bool

IsSubtractWithBorrow checks whether or not this corresponds with a "subtract with borrow" operation, or not.

func SkipTargets added in v1.2.21

func SkipTargets[W Word[W]](b Bytecode[W], from uint) []uint

SkipTargets returns, for a skip-like bytecode located at bytecode index `from` within its enclosing vector, the index of each bytecode to which control may transfer when the skip is taken. A skip over n bytecodes transfers to `from + n + 1` (mirroring the interpreter's control flow). For non-skip bytecodes, nil is returned.

func ValidateProgram added in v1.2.22

func ValidateProgram[W word.Word[W]](p Program[W]) error

ValidateProgram performs various sanity checks on the bytecode vectors of each function within a program. Sanity checks include: (1) ensuring that vectors themselves are well-formed (e.g. with respect to write conflicts, jump/skip destinations, terminal instructions, etc); (2) that each individual bytecode is well formed within its function. For example, that: any registers it refers to actually exist; that registers it uses are of the correct form (e.g. some instructions cannot operate on native registers); that any call targets exist and are functions and, likewise, that any memory accesses exist and are memories. It returns nil when no problems are found.

Types

type Address added in v1.2.21

type Address = bytecode.Address

Address provides a convenient alias for a branch target address.

type BinaryProgram added in v1.2.21

type BinaryProgram[W Word[W]] = encoding.Binary[W]

BinaryProgram represents a compiled bytecode program, along with accompanying symbolic information. This is primarily useful for debugging.

func CompileProgram added in v1.2.21

func CompileProgram[W word.Word[W]](p Program[W]) BinaryProgram[W]

CompileProgram compiles a program descriptor into an binary (i.e. executable) bytecode program.

type Bytecode

type Bytecode[W Word[W]] = bytecode.Bytecode[W]

Bytecode encapsulates a single bytecode instruction.

func Add added in v1.2.21

func Add[W Word[W]](target RegisterId, sources []RegisterId, constant W) Bytecode[W]

Add constructs an addition instruction computing "target = sum(sources) + constant" into a single target register.

func AddModP added in v1.2.21

func AddModP[W Word[W]](target RegisterId, sources []RegisterId, constant W) Bytecode[W]

AddModP constructs a field-addition instruction computing "target = sources[0] + ... + constant" modulo the field prime.

func AddVec added in v1.2.21

func AddVec[W Word[W]](targets []RegisterId, sources []RegisterId) Bytecode[W]

AddVec constructs a vectored addition instruction computing "targets = sum(sources)" (i.e. with no constant addend), where targets is a multi-limb register vector.

func AddVecConst added in v1.2.21

func AddVecConst[W Word[W]](targets []RegisterId, sources []RegisterId, constant W) Bytecode[W]

AddVecConst constructs a vectored addition instruction computing "targets = sum(sources) + constant", where targets is a multi-limb register vector.

func Assign added in v1.2.21

func Assign[W Word[W]](target RegisterId, source RegisterId) Bytecode[W]

Assign constructs a assignment which copies the source register into the target register.

func AssignV added in v1.2.21

func AssignV[W Word[W]](targets []RegisterId, sources ...RegisterId) Bytecode[W]

AssignV constructs a concatenation instruction which concatenates the source registers and assigns to a given target register vector.

func BitAnd added in v1.2.21

func BitAnd[W Word[W]](target, left, right RegisterId, bitwidth uint16) Bytecode[W]

BitAnd constructs a bitwise-and instruction computing "target = left & right". bitwidth is the operand/result width in bits.

func BitNot added in v1.2.21

func BitNot[W Word[W]](target, source RegisterId, bitwidth uint16) Bytecode[W]

BitNot constructs a bitwise-not instruction computing "target = ^source". bitwidth is the width (in bits) the complement is taken within, so the result holds only the low bitwidth bits of ^source.

func BitOr added in v1.2.21

func BitOr[W Word[W]](target, left, right RegisterId, bitwidth uint16) Bytecode[W]

BitOr constructs a bitwise-or instruction computing "target = left | right". bitwidth is the operand/result width in bits.

func BitShl added in v1.2.21

func BitShl[W Word[W]](target, left, right RegisterId, bitwidth uint16) Bytecode[W]

BitShl constructs a logical shift-left instruction computing "target = left << right". bitwidth is the result width in bits; bits shifted out beyond it are discarded.

func BitShr added in v1.2.21

func BitShr[W Word[W]](target, left, right RegisterId, bitwidth uint16) Bytecode[W]

BitShr constructs a logical shift-right instruction computing "target = left >> right". bitwidth is the operand/result width in bits.

func BitXor added in v1.2.21

func BitXor[W Word[W]](target, left, right RegisterId, bitwidth uint16) Bytecode[W]

BitXor constructs a bitwise-xor instruction computing "target = left ^ right". bitwidth is the operand/result width in bits.

func Call added in v1.2.21

func Call[W Word[W]](target ModuleId, args []RegisterId, returns []RegisterId) Bytecode[W]

Call constructs a function-call bytecode with the given flags.

func CheckCast added in v1.2.21

func CheckCast[W Word[W]](target RegisterId, bitwidth uint16) Bytecode[W]

CheckCast constructs a check-cast instruction asserting that the given target register fits within the given bit width.

func Debug added in v1.2.21

func Debug[W Word[W]](chunks []FormattedChunk, sources []RegisterId) Bytecode[W]

Debug constructs a debug instruction carrying the given formatted message.

func Div added in v1.2.21

func Div[W Word[W]](target, dividend, divisor RegisterId) Bytecode[W]

Div constructs an integer-division instruction computing "target = dividend / divisor".

func Fail added in v1.2.21

func Fail[W Word[W]](chunks []FormattedChunk, sources []RegisterId) Bytecode[W]

Fail constructs a fail instruction carrying the given formatted message.

func Intrinsic added in v1.2.21

func Intrinsic[W Word[W]](op bytecode.Operation, targets, sources []bytecode.RegisterVector) Bytecode[W]

Intrinsic constructs a hint instruction performing the given operation op (e.g. DIV_HINT) which reads the given source (argument) register vectors and writes the given target (return) register vectors.

func Jump added in v1.2.21

func Jump[W Word[W]](target Address) Bytecode[W]

Jump creates an unconditional jump instruction transferring control to the given target address.

func LoadConst added in v1.2.21

func LoadConst[W Word[W]](target RegisterId, constant W) Bytecode[W]

LoadConst constructs an instruction assigning a constant into a single target register.

func MemRead added in v1.2.21

func MemRead[W Word[W]](id uint16, address []RegisterId, data []RegisterId) Bytecode[W]

MemRead constructs a memory-read instruction. The data registers receive the row located at the address given by the address registers, in the memory identified by id. The kind of memory being read (ROM, static ROM, RAM, paged RAM) is resolved from the environment when the instruction is encoded.

func MemWrite added in v1.2.21

func MemWrite[W Word[W]](id uint16, address []RegisterId, data []RegisterId) Bytecode[W]

MemWrite constructs a memory-write instruction. The data registers are written to the row located at the address given by the address registers, in the memory identified by id. The kind of memory being written (write-once, RAM, paged RAM) is resolved from the environment when the instruction is encoded.

func Mul added in v1.2.21

func Mul[W Word[W]](target RegisterId, sources []RegisterId, constant W) Bytecode[W]

Mul constructs a multiplication instruction computing "target = product(sources) * constant" into a single target register.

func MulModP added in v1.2.21

func MulModP[W Word[W]](target RegisterId, sources []RegisterId, constant W) Bytecode[W]

MulModP constructs a field-multiplication instruction computing "target = sources[0] * ... * constant" modulo the field prime.

func MulVec added in v1.2.21

func MulVec[W Word[W]](targets []RegisterId, sources []RegisterId, constant W) Bytecode[W]

MulVec constructs a vectored multiplication instruction computing "targets = product(sources) * constant", where targets is a multi-limb register vector.

func Rem added in v1.2.21

func Rem[W Word[W]](target, dividend, divisor RegisterId) Bytecode[W]

Rem constructs an integer-remainder instruction computing "target = dividend % divisor".

func Return added in v1.2.21

func Return[W Word[W]]() Bytecode[W]

Return constructs a return instruction with the given frame width and return offset.

func Skip added in v1.2.21

func Skip[W Word[W]](skip uint16) Bytecode[W]

Skip constructs an uncondition skip instruction which skips over n instructions.

func SkipIf added in v1.2.21

func SkipIf[W Word[W]](op Cond, skip uint16, left, right RegisterId) Bytecode[W]

SkipIf constructs a conditional branch instruction which jumps to the target address when "left op right" holds, comparing single registers.

func Sub added in v1.2.21

func Sub[W Word[W]](target RegisterId, sources []RegisterId, constant W) Bytecode[W]

Sub constructs a subtraction instruction computing "target = sources[0] - ... - constant" into a single target register.

func SubModP added in v1.2.21

func SubModP[W Word[W]](target RegisterId, sources []RegisterId, constant W) Bytecode[W]

SubModP constructs a field-subtraction instruction computing "target = sources[0] - ... - constant" modulo the field prime.

func SubVec added in v1.2.21

func SubVec[W Word[W]](targets []RegisterId, sources []RegisterId, constant W) Bytecode[W]

SubVec constructs a vectored subtraction instruction computing "targets = sources[0] - ... - constant", where targets is a multi-limb register vector.

func Switch added in v1.2.21

func Switch[W Word[W]](source RegisterId, cases []SwitchCase[W]) Bytecode[W]

Switch constructs a multiway-skip (SMW) instruction which dispatches on the value of the source register against the given (value, target) table.

type BytecodeArith added in v1.2.21

type BytecodeArith[W Word[W]] = bytecode.Arith[W]

BytecodeArith is an integer arithmetic bytecode (target = op(sources) op constant).

type BytecodeCall added in v1.2.21

type BytecodeCall[W Word[W]] = bytecode.Call[W]

BytecodeCall is a function-call bytecode.

type BytecodeCat added in v1.2.21

type BytecodeCat[W Word[W]] = bytecode.Cat[W]

BytecodeCat is a concatenation bytecode (target vector = sources joined by width).

type BytecodeCheckCast added in v1.2.21

type BytecodeCheckCast[W Word[W]] = bytecode.CheckCast[W]

BytecodeCheckCast is a width-check (cast) bytecode.

type BytecodeDebug added in v1.2.21

type BytecodeDebug[W Word[W]] = bytecode.Debug[W]

BytecodeDebug is a debug bytecode.

type BytecodeEnvironment added in v1.2.21

type BytecodeEnvironment[W Word[W]] = bytecode.Environment[W]

BytecodeEnvironment provides information about the enclosing environment of a bytecode, and is primarily for debugging and validation.

type BytecodeFail added in v1.2.21

type BytecodeFail[W Word[W]] = bytecode.Fail[W]

BytecodeFail is a fail bytecode.

type BytecodeFieldArith added in v1.2.21

type BytecodeFieldArith[W Word[W]] = bytecode.FieldArith[W]

BytecodeFieldArith is a field arithmetic bytecode (target = op(sources) op constant mod P).

type BytecodeIntrinsic added in v1.2.21

type BytecodeIntrinsic[W Word[W]] = bytecode.Intrinsic[W]

BytecodeIntrinsic is a (non-deterministic) hint bytecode.

type BytecodeJmp added in v1.2.21

type BytecodeJmp[W Word[W]] = bytecode.Jmp[W]

BytecodeJmp is an unconditional jump bytecode.

type BytecodeReadWrite added in v1.2.21

type BytecodeReadWrite[W Word[W]] = bytecode.ReadWrite[W]

BytecodeReadWrite is a memory read/write bytecode.

type BytecodeRet added in v1.2.21

type BytecodeRet[W Word[W]] = bytecode.Ret[W]

BytecodeRet is a return bytecode.

type BytecodeSkip added in v1.2.21

type BytecodeSkip[W Word[W]] = bytecode.Skip[W]

BytecodeSkip is an unconditional skip bytecode.

type BytecodeSkipIf added in v1.2.21

type BytecodeSkipIf[W Word[W]] = bytecode.SkipIf[W]

BytecodeSkipIf is a conditional skip bytecode.

type BytecodeSwitch added in v1.2.21

type BytecodeSwitch[W Word[W]] = bytecode.Switch[W]

BytecodeSwitch is a multiway-skip (switch) bytecode.

type BytecodeVector added in v1.2.21

type BytecodeVector[W Word[W]] = bytecode.Vector[W]

BytecodeVector bundles together one or more bytecode instructions which, with restrictions, can be executed by the underlying machine "in parallel". The approach is analoguous to the concept of "Very-Long Instruction Words (VLIW)" but taken to more of an extreme --- there is no limit on the number of bytecode instructions.

To better understand bytecode vectors, consider two instructions executed in sequence (the at pc location 0, the second at pc location 1):

(pc=0) x = y + 1 (pc=1) z = 0

When executing these instructions, there is an intermediate state after the first instruction is executed but before the second has been where x has been written but z has not. Alternatively, the two instructions can be composed together to form a bytecode vector, written like so:

(pc=0) x = y + 1 ; z = 0

In this case, both instructions are executed together and there is no intermediate state where x is written but z is not.

To ensure easy translation into polynomial constraints, there are restrictions on how bytecode vectors can be composed. In particular, no variable can be assigned twice on the same execution path. Thus, for example, this is an invalid bytecode vector:

(pc=0) x = 0 ; x = 1

These writes are said to be _conflicting_. In contrast, the following is a valid bytecode vector:

(pc=0) skip_if x != y 2 ; r = 0 ; ret ; r = 1 ; ret

In this case, whilst there are two assignments to register r, neither are on the same path. These writes are said to be _non-conflicting_. Finally, we should note that register forwarding is applied within bytecode vectors. Thus, for example, the following is allowed:

(pc=0) x = 0; y = x + 1; ret

Here, the value of x written in the instruction is "forwarded" to the assignment for y. This process is, roughly speaking, analoguous to register forwarding as found in CPU architectures.

func NewBytecodeVector added in v1.2.21

func NewBytecodeVector[W word.Word[W]](codes ...Bytecode[W]) BytecodeVector[W]

NewBytecodeVector constructs a bytecode vector (single trace line) from the given bytecodes.

type CheckPoint

type CheckPoint[W word.Word[W]] = checkpoint.CheckPoint[W]

CheckPoint represents a captured state of an executing machine, such that execution can be continued later from this position (sometimes also known as a "continuation"). As such, the checkpoint must include all information necessary to allow execution to continue. However, to reduce the size of a checkpoint, certain optimsiations of this information are permitted. As such, implementations can manage this information in different ways (e.g. using compression, read-access lists, page-access lists, etc).

For example suppose that a machine, upon reaching the checkpoint, has 1GB of some RAM allocated. A full checkpoint would include all of this data and, therefore, be at least 1GB in size. Suppose, however, that executing the machine from this point onwards only requires accessing 1MB of data from that RAM. Then, in fact, a valid implementation might only store that 1MB of information (e.g. to reduce network transport costs, or proof size, etc).

Finally, to support more aggressive optimisation, checkpoints have a notion of their "validity window". To understand this, consider a refinement of the example above. Suppose there are M execution steps remaining from the checkpoint until the machine terminates, but that executing these M steps now requires the full 1GB of RAM. However, we now suppose that executing the next N steps requires accessing only 1MB of that RAM. Then, the checkpoint may only store that 1MB of data if it is marked as being valid for (upto) N steps of execution. The purpose of this is to allow a program's execution to be broken up into multiple checkpoints, such that each checkpoint only stores the data it requires for executing its portion of the overall execution.

type Cond added in v1.2.21

type Cond = bytecode.Condition

Cond provides a convenient alias for the comparison condition used by conditional skip instructions.

type Core

type Core[W Word[W]] interface {
	// Boot this machine by starting the given function with the given inputs.  This
	// function assumes the given inputs are correctly formed, and will: (1) ingore
	// unknown inputs; (2) initialise empty memories when no input is given for
	// them.  Thus, it is recommended to perform sanity checking on input prior to
	// calling this function.
	Boot(fun string, input map[string][]W) error
	// Execute the machine for the given number of steps, returning the actual
	// number of steps executed and an error (if execution failed).
	Execute(steps uint) (uint, error)
	// Return array of (non-static) input memories
	Inputs() iter.Iterator[interpreter.InputOutput[W]]
	// Return array of output memories
	Outputs() iter.Iterator[interpreter.InputOutput[W]]
}

Core provides a minimal interface for booting and executing a machine with a given set of inputs, and collecting the outputs afterwards.

type FormattedChunk added in v1.2.21

type FormattedChunk = bytecode.FormattedChunk

FormattedChunk describes a single chunk of a formatted (debug/fail) message.

func NewFormattedChunk added in v1.2.21

func NewFormattedChunk(text string, format zkc_util.Format) FormattedChunk

NewFormattedChunk constructs a formatted (debug/fail) message chunk from its text, format directive and (optional) argument registers. The argument registers are bundled into the chunk's register vector internally, so callers work purely in terms of RegisterId.

type Function

type Function[W Word[W]] = descriptor.Function[W]

Function contains information about an executable function in the system. A function has one or more registers where: the first n registers are the input registers (i.e. parameters); the next m registers are the output registers (i.e. returns); and all remaining registers are internal (sometimes also referred to as computed registers). Additionally, a function has some number of "instructions" which capture its semantics (i.e. intended behaviour). The notion of an instruction is specifically left undefined by this interface to support different levels of the compilation pipeline. For example, a compiled function has instructions which are simply bytes (or words) for efficient execution. However, the instructions of an "assembly" level function implement the Instruction interface, which is better suited to analysis and/or translation into constraints.

func NewBytecodeFunction added in v1.2.21

func NewBytecodeFunction[W word.Word[W]](name string, kind FunctionKind, registers []Register[W],
	code ...BytecodeVector[W]) *Function[W]

NewBytecodeFunction constructs a bytecode (descriptor) function module from its registers and a body of bytecode vectors.

type FunctionKind added in v1.2.22

type FunctionKind = descriptor.FunctionKind

FunctionKind identifies whether a function is implemented by bytecode or a native circuit and whether calls may supply undefined arguments.

type GoGenConfig

type GoGenConfig = gogen.Config

GoGenConfig controls the shape of the Go source GenerateGo produces.

type Interpreter added in v1.2.21

type Interpreter[W Word[W]] = interpreter.Interpreter[W]

Interpreter is an optimised bytecode interpreter for executing word instructions.

func NewBytecodeInterpreter added in v1.2.21

func NewBytecodeInterpreter[W word.Word[W]](program Program[W]) *Interpreter[W]

NewBytecodeInterpreter constructs an interpreter for executing the given bytecode program. The modulus is the prime characteristic of the surrounding field, used when executing native field instructions.

type Memory

type Memory[W Word[W]] = descriptor.Memory[W]

Memory describes the familiar notion of a "machine memory" which can be read-only, write-only or read-write. Furthermore, memory can be static (i.e. its contents are fixed for all executions of a machine).

func NewBytecodeMemory added in v1.2.21

func NewBytecodeMemory[W word.Word[W]](name string, kind MemoryKind, registers []Register[W], init ...W,
) *Memory[W]

NewBytecodeMemory constructs a memory (descriptor) module directly from its name, kind and registers. Since a memory has no body, this descriptor is its final form (cf. NewBytecodeFunction). The geometry is derived from the registers; init supplies the static contents and must be empty for non-static memories.

type MemoryKind added in v1.2.21

type MemoryKind = descriptor.MemoryKind

MemoryKind identifies the kind of a memory: its access mode (read-only, write-once or read-write), its visibility (public/private), and whether it is static or paged. Used with NewBytecodeMemory.

type Module

type Module[W Word[W]] = descriptor.Module[W]

Module describes a moddule, such as a function or memory

type ModuleId added in v1.2.21

type ModuleId = bytecode.ModuleId

ModuleId provides a convenient alias for a module identifier.

type Operation added in v1.2.21

type Operation = bytecode.Operation

Operation identifies the operation performed by an arithmetic / field / bitwise / hint bytecode (see the OP_* constants).

type Program added in v1.2.21

type Program[W Word[W]] = descriptor.Program[W]

Program represents a bytecode assembly program.

func AddRangeConstraints added in v1.2.21

func AddRangeConstraints[W word.Word[W]](cfg field.Config, program Program[W], maxStaticDepth uint) Program[W]

AddRangeConstraints adds a range-proof constraint for each register in the program. This is done by adding lookups from each (non-constant) register to a precomputed table of all valid values for that register width.

func FactorSkipConditions

func FactorSkipConditions[W word.Word[W]](program Program[W]) Program[W]

FactorSkipConditions rewrites equality SkipIf bytecodes (EQ/NEQ) so that the branch condition is materialised once into a fresh 1-bit register, rather than being replicated across each guarded write of the branch.

NOTE: This transform must run after vectorisation and before register splitting.

func FlattenCalls added in v1.2.21

func FlattenCalls[W word.Word[W]](program Program[W]) Program[W]

FlattenCalls introduces a tmp register to hold a call argument when it's rewritten in the same vector: 1. x = f(x) 2. y = f(x); x = x + 1 As we want to avoid shift in lookups, we must keep the original value of x in a tmp register, so that the call can be rewritten as: 1. tmp = x; x = f(tmp) 2. tmp = x; y = f(tmp); x = x + 1

func InlineFunctions

func InlineFunctions[W word.Word[W]](program Program[W], names []string) Program[W]

InlineFunctions returns an equivalent bytecode program in which every call to one of the named functions has been inlined at its call site, and the named function modules removed (module identifiers within Call / ReadWrite bytecodes are remapped accordingly). Each call site is replaced by the callee's body operating on caller registers: inputs / outputs are aliased directly to the call's argument / return registers where provably equivalent; otherwise (e.g. for temporaries, or aliasing call sites such as "x = f(x)") fresh caller-local shadow registers are allocated, along with argument / return copies which preserve the dynamic width checks of a true call.

NOTE: This transform must be applied before vectorisation, since it splits the vector enclosing a call at the call site.

func InsertCheckCasts added in v1.2.21

func InsertCheckCasts[W word.Word[W]](program Program[W]) Program[W]

InsertCheckCasts inserts the width-check (CHECKCAST) bytecodes required by a bytecode program, returning the updated program. Codegen emits operations without casts; this pass adds the cast checks each operation needs (resolving call / memory references against the program's module signatures) and rewrites branch offsets accordingly. It must run on a complete program.

func LowerBitwise

func LowerBitwise[W word.Word[W]](program Program[W]) Program[W]

LowerBitwise rewrites VM-level bitwise bytecodes into CALLs to helper functions, returning the updated bytecode program (the helper function modules are appended to it).

NOTE: this transform must be applied BEFORE vectorization and register splitting.

func LowerComparisons

func LowerComparisons[W word.Word[W]](program Program[W]) Program[W]

LowerComparisons rewrites SkipIf bytecodes with LT/GT/LTEQ/GTEQ conditions into arithmetic-only sequences using biased subtraction and sign-bit extraction. EQ and NEQ conditions are left unchanged.

func LowerDivisions

func LowerDivisions[W word.Word[W]](program Program[W]) Program[W]

LowerDivisions rewrites INT_DIV and INT_REM bytecodes into a non-deterministic hint followed by arithmetic validation:

Hint{DIV_HINT, q, r, w, x, y}   // prover fills quotient, remainder and range witness
qy = q * y
z0 = x - qy - r          // written into a 0-width register: asserts == 0
z1 = y - r - w - 1       // written into a 0-width register: asserts == 0

This is a bytecode-level transform, so it runs before the program is decompiled into a word machine.

NOTE: This pass must run before LowerComparisons.

func LowerOrXorAnd added in v1.2.22

func LowerOrXorAnd[W word.Word[W]](program Program[W], maxStaticDepth uint) Program[W]

LowerOrXorAnd rewrites bitwise AND/OR/XOR bytecodes into either a static-table lookup (a memory read) or a CALL to a recursive helper function, returning the updated bytecode program (the helper / table modules are appended to it). An operation whose width is small enough that its 2^(2*width)-row truth table fits within maxStaticDepth is realised as a table read; wider operations are lowered recursively until their leaves are.

NOTE: unlike LowerBitwise, this transform must be applied AFTER register splitting and BEFORE range-constraint generation.

func LowerSwitch added in v1.2.21

func LowerSwitch[W word.Word[W]](program Program[W]) Program[W]

LowerSwitch rewrites Switch (multiway skip) bytecodes into equivalent sequences of SkipIf bytecodes. Each dispatch case becomes a constant load of the case's value into a fresh register, followed by a conditional (EQ) skip against the dispatch register targeting the case's original destination. Cases are tested in order, preserving the first-match-wins semantics of the multiway dispatch; when no case matches, control falls through exactly as before.

NOTE: this transform must run before register splitting (which does not support Switch bytecodes).

func NewBytecodeProgram added in v1.2.21

func NewBytecodeProgram[W word.Word[W]](field field.Config, modules ...Module[W]) Program[W]

NewBytecodeProgram assembles a bytecode program directly from pre-lowered descriptor modules, bypassing the word-machine round trip.

func OptimizeDivisions

func OptimizeDivisions[W word.Word[W]](program Program[W]) Program[W]

OptimizeDivisions is a fast-mode optimization which rewrites division by powers of 2 into right shifts, and remainder by powers of 2 into bitwise ANDs.

func ProgramToProgram added in v1.2.21

func ProgramToProgram[W1 word.Word[W1], W2 word.Word[W2]](p Program[W1]) Program[W2]

ProgramToProgram transforms a bytecode program operating over a given word type (W1) into an identical program which operates over a different word type (W2). Generally speaking, we are going from a larger word (e.g. word.Uint) to a smaller word (e.g. word.Uint64). This is the program-level analogue of WordToWordMachine.

The transformation is purely structural: bytecodes are re-typed but not rewritten or lowered, register declarations are preserved verbatim (no splitting or width changes), and constants are not reduced modulo the field. Static memory contents are converted element-wise; non-static memories carry no contents in either representation.

This function will panic if it encounters a register, constant or memory cell which exceeds the bandwidth of W2. Callers needing to target a narrower word size than some source register widths should run SplitRegisters first.

func SplitRegisters

func SplitRegisters[W word.Word[W]](cfg WordConfig, program Program[W]) Program[W]

SplitRegisters all modules to meet a given bandwidth and maximum register width. This will split all registers wider than the maximum permitted width into two or more "limbs" (i.e. subregisters which do not exceeded the permitted width). For example, consider a register "r" of width u32. Subdividing this register into registers of at most 8bits will result in four limbs: r'0, r'1, r'2 and r'3 where (by convention) r'0 is the least significant.

func Vectorize added in v1.2.21

func Vectorize[W word.Word[W]](program Program[W]) Program[W]

Vectorize merges as many bytecodes as possible into each (vector / trace-line) bytecode, subject to register-conflict (data hazard) constraints.

type ProgramPoint added in v1.2.21

type ProgramPoint = descriptor.ProgramPoint

ProgramPoint identifies a specific bytecode instruction within a given bytecode program. A key aspect is that it two dimensional to account for bytecode vectors: (1) it identifies the enclosing bytecode vector (macro) being executed; (2) it identifies the exact bytecode instruction (micro) within that being executed.

type Register added in v1.2.21

type Register[W Word[W]] = descriptor.Register[W]

Register describes a register

func NewComputedRegister added in v1.2.21

func NewComputedRegister[W word.Word[W]](name string, bitwidth util.Option[uint], padding W) Register[W]

NewComputedRegister constructs a computed register descriptor of the given name and bit-width. A bit-width of math.MaxUint yields a native (field) register, which carries no fixed bit-width.

func NewInputRegister added in v1.2.21

func NewInputRegister[W word.Word[W]](name string, bitwidth util.Option[uint], padding W) Register[W]

NewInputRegister constructs an input register descriptor of the given name and bit-width. A bit-width of math.MaxUint yields a native (field) register, which carries no fixed bit-width.

func NewOutputRegister added in v1.2.21

func NewOutputRegister[W word.Word[W]](name string, bitwidth util.Option[uint], padding W) Register[W]

NewOutputRegister constructs an output register descriptor of the given name and bit-width. A bit-width of math.MaxUint yields a native (field) register, which carries no fixed bit-width.

func NewRegister added in v1.2.21

func NewRegister[W word.Word[W]](kind register.Type, name string, bitwidth util.Option[uint],
	padding W) Register[W]

NewRegister constructs a new register descriptor, where native registers are indicated by the absence of any specific bitwidth.

type RegisterId added in v1.2.21

type RegisterId = bytecode.RegisterId

RegisterId identifies a register within a module. It is the register identifier used throughout the bytecode layer (an alias of the internal bytecode RegisterId).

type RegisterVector added in v1.2.21

type RegisterVector = bytecode.RegisterVector

RegisterVector is a contiguous span of registers (a multi-limb operand).

type RuntimeMemory added in v1.2.21

type RuntimeMemory[W Word[W]] = interpreter.Memory[W]

RuntimeMemory captures the notion of an executing memory, rather than a simple static descriptor. That is, one whose current contents can be accessed.

type State added in v1.2.21

type State[W any] struct {
	// contains filtered or unexported fields
}

State collects together information recorded when executing a single vector instruction.

func (State[W]) Fid added in v1.2.21

func (p State[W]) Fid() uint16

Fid returns the identifier of the function (module) this state belongs to.

func (State[W]) Frame added in v1.2.21

func (p State[W]) Frame() []W

Frame returns frame data stored in this state

func (State[W]) IsTerminal added in v1.2.21

func (p State[W]) IsTerminal() bool

IsTerminal indicates whether or not this is a "terminal state" for the enclosing function.

func (State[W]) PC added in v1.2.21

func (p State[W]) PC() uint

PC returns the value of program counter for this state.

func (State[W]) Width added in v1.2.21

func (p State[W]) Width() uint

Width returns with the width of this state.

type SwitchCase added in v1.2.21

type SwitchCase[W any] = bytecode.SwitchCase[W]

SwitchCase is a single (value, target) entry of a multiway-skip dispatch table.

type TraceProcessor added in v1.2.21

type TraceProcessor[W Word[W], F any] interface {
	// Post-process the trace for a given function.
	TraceFunction(Function[W], []State[W]) rtrace.ArrayModule[F]
	// Post-process the trace for a memory of some kind
	TraceMemory(m RuntimeMemory[W]) rtrace.ArrayModule[F]
}

TraceProcessor captures the notion of a "post-processing" function on the data recorded during execution for a given module. The goal of this is to decouple post-processing logic from the trace observer itself.

type Uint

type Uint = word.Uint

Uint represents an unbound unsigned integer.

type Uint64

type Uint64 = word.Uint64

Uint64 represents an 64-bit unsigned integer.

type Uint128

type Uint128 = word.Uint128

Uint128 represents an 128-bit unsigned integer.

type Word

type Word[W any] = word.Word[W]

Word abstracts the data type (a.k.a the "machine word") used for holding values within the machine. The reason for abstracting this concept is to allow a machine compiled for a larger word size to be automatically lowered to a machine for a smaller word size. For example, our source program might be written for a 64bit machine and we wish to executed it on 16bit machine (i.e. because our target field configuration has a maximum register size of 16bits).

type WordConfig

type WordConfig = word.Config

WordConfig provides necessary configuration information about a given target word.

Directories

Path Synopsis
internal
checkpoint
Package checkpoint provides the data structures used to capture (a snapshot of) the state of an executing machine, so that execution can later be resumed from that point.
Package checkpoint provides the data structures used to capture (a snapshot of) the state of an executing machine, so that execution can later be resumed from that point.
descriptor
Package descriptor describes the static structure of a compiled bytecode program, independently of the bytecode instruction stream itself.
Package descriptor describes the static structure of a compiled bytecode program, independently of the bytecode instruction stream itself.
gogen
Package gogen compiles a ZkC bytecode program into native Go source: the "fast execution mode" alternative to interpreting the program.
Package gogen compiles a ZkC bytecode program into native Go source: the "fast execution mode" alternative to interpreting the program.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL