Circuit and Proof¶
Circuit Example¶
zkMove is designed to be developer-friendly and fits naturally into existing Move development workflows. By leveraging the standard Move package structure, zkMove lets you define zk circuits alongside your Move code with minimal configuration changes.
The example below is a Move module that computes the Fibonacci sequence. The full source can be found in the example directory of the halo2-verifier.move repository. We will build a zk circuit for the test_fibonacci entry function.
// fibonacci.move
module 0x1::fibonacci {
public entry fun test_fibonacci(n: u64) {
let value1 = 0u256;
let value2 = 1u256;
let fibo = 0u256;
let i = 0u64;
while (i < n) {
fibo = value1 + value2;
value1 = value2;
value2 = fibo;
i = i + 1;
};
fibo;
}
}
To define a circuit for this function, add a [circuit.<name>] section to the package manifest Move.toml. In this example, the circuit is named fibonacci:
[package]
name = "example"
version = "0.0.1"
[dependencies]
MoveStdlib = { git = "https://github.com/zkmove/aptos-core.git", subdir = "third_party/move/move-stdlib", rev = "witnessing" }
[addresses]
std = "0x1"
[circuit.fibonacci]
max_execution_rows = 278 # Max rows for the execution subcircuit.
max_poseidon_rows = 100 # Max rows for the Poseidon subcircuit.
entry = { module_id = "0x1::fibonacci", function_name = "test_fibonacci" }
Generate a Witness¶
First, build the example package. The zkmove vm commands read the compiled
package from the Move build output.
# Run from the package root (the directory containing `Move.toml`).
move build --skip-fetch-latest-git-deps
Then execute the entry function with zkmove vm dry-run to generate the
witness. By default, witness files are written to the witnesses/ directory:
zkmove vm \
--package-path ./ \
--circuit-name fibonacci \
dry-run --args 10u64
# Reuse the witness generated by this run in the following commands.
export WITNESS="$(find witnesses -type f -name 'test_fibonacci-*.json' -print | sort | tail -n 1)"
test -f "$WITNESS"
Generate Setup Artifacts¶
Before proving, generate the app-developer setup artifacts for this circuit.
The command writes params.bin, pk.bin, vk.bin, and metadata.json to
setup/ by default:
zkmove vm \
--package-path ./ \
--circuit-name fibonacci \
setup \
--params-path params/kzg_bn254_12.srs \
--witness "$WITNESS"
If your circuit exposes one or more entry arguments as public inputs, add the same public-input indices here. For example:
zkmove vm \
--package-path ./ \
--circuit-name fibonacci \
setup \
--params-path params/kzg_bn254_12.srs \
--witness "$WITNESS" \
--pubs-indices 0
Use the same --pubs-indices values later when building on-chain verifier
artifacts for this circuit.
Generate a Proof¶
Run the following command from the package root. Replace the witness filename with the one generated in the previous step:
zkmove vm \
--package-path ./ \
--circuit-name fibonacci \
prove -w "$WITNESS"
export RUN_ID="$(basename "$WITNESS" .json)"
export PUBS_PATH="proofs/${RUN_ID}.instance"
export PROOF_PATH="proofs/${RUN_ID}.proof"
Optional: verify locally before submitting on-chain.
zkmove vm \
--package-path ./ \
--circuit-name fibonacci \
verify \
--pubs-path "$PUBS_PATH" \
--proof-path "$PROOF_PATH"
prove and verify read setup/metadata.json, setup/params.bin,
setup/pk.bin, and setup/vk.bin by default. Use --setup-dir <dir> if you
store those setup artifacts elsewhere.