Skip to main content

Precompiles and syscalls

This page shows you where each guest hands work to its zkVM's dedicated circuits, which call reaches which circuit, and what stays in plain RISC-V code.

Hashing and curve math take many RISC-V instructions, and a zkVM proves every instruction it runs, so plain code for these routines makes a long trace. That is why each zkVM offers dedicated circuits for them. The guest reaches a circuit through an ecall on SP1, or through a CSR access on Airbender and ZisK. Each such call replaces a software routine the prover would otherwise trace cycle by cycle.

SP1 ecalls​

Both Hypercube guests declare their ecalls in prover/guest_hypercube/src/include/sp1_syscalls.hpp. Most wrappers are always inlined and compile to a single ecall, and most call sites sit in ZVM1, the evmone fork in third_party/evmone.

EcallsCalled fromUsed for
keccak_permutelib/evmone_precompiles/keccak.cEvery Keccak-256 hash: KECCAK256, trie nodes, addresses
sha256_extend, sha256_compresslib/evmone_precompiles/sha256.cppThe SHA256 precompile, and the public-values digest
secp256k1_add, secp256k1_doublelib/evmone_precompiles/secp256k1.cppECRECOVER and transaction sender recovery
uint256_mulmodlib/evmone/instructions.hpp, lib/evmone_precompiles/modexp.cppADDMOD, MULMOD and MODEXP
bn254_fp_*mod, bn254_fp2_*modlib/evmone_precompiles/modarith.hpp, pairing/field_template.hppField math for ECADD, ECMUL and ECPAIRING
bn254_add, bn254_doubleevmone's precompile dispatch, test/state/precompiles.cppPoint math for ECADD and ECMUL
bls12381_fp_*mod, bls12381_fp2_*modcmake/patch_blst_sp1.sh, a build-time patch of blstThe BLS12-381 precompiles and KZG point evaluation

The header also declares ecalls that nothing in the guest calls at the current ZVM1 pin. Those are the secp256r1 and ed25519 point ecalls, bls12381_add and bls12381_double, u256x2048_mul, and the two uint256_*_with_carry calls.

Public values take a different route. The guest commits them by writing to file descriptor 13, SP1_FD_PUBLIC_VALUES, and the runtime in prover/guest_hypercube/src/sp1_runtime.cpp buffers those bytes. At halt it hashes them with SHA-256 and commits the digest.

Airbender CSRs​

The Airbender guest reaches its delegation circuits by writing to CSRs, which prover/guest_airbender/src/include/airbender_csr.hpp names.

CSRNameUse in the guest
0x7C0Non-determinism oracleReads the input words and writes log output
0x7CABigInt256-bit add, subtract, multiply, compare and copy
0x7CC, 0x7CD, 0x7CEkeccak_f1600: theta and rho, column parity, chi5One Keccak permutation per run of writes
0x7C7Blake2sDeclared only; no guest code calls it

The curve and scalar logic around these calls stays RISC-V code in ZVM1. The alpha.5 release notes map each precompile to a delegation:

PrecompileDelegationCode path
ECRECOVER, and every transaction's sender recoveryBigIntevmone's secp256k1, with Montgomery field arithmetic on BigInt
SHA256, RIPEMD160, IDENTITY, BLAKE2FNonePlain rv32 code
MODEXPBigIntMontgomery exponentiation for 256-bit operands; the generic path otherwise
ECADD, ECMUL, ECPAIRINGBigIntbn254 field arithmetic
POINT_EVALUATION and the BLS12-381 precompilesBigIntblst, patched at build time to multiply on BigInt
P256VERIFYBigIntevmone's generic Montgomery field template
KECCAK256, and every hash the guest computeskeccak_f1600One delegation run per permutation

BigInt also carries the EVM's own 256-bit add, subtract and multiply, along with its 32-byte copies.

ZisK CSRs on PR #86​

The ZisK guest exists only on draft PR #86. It calls ZisK's CSR precompiles, in the range 0x800 to 0x819, and its memcpy, memmove, memset and memcmp go to ZisK's DMA precompiles.

AreaZisK precompiles
keccak-f0x800
SHA2560x805
ADDMOD, MULMOD, and MODEXP up to 32-byte operands0x802
ECRECOVER0x802, 0x803, 0x804, plus square-root, inverse and GLV-split hints
ECADD, ECMUL, ECPAIRING0x802, 0x806, 0x807, 0x808 to 0x80A
BLS12-381 and KZG, through patched blst0x80B, 0x80E to 0x810, plus an inverse hint
BLAKE2F0x819
P256VERIFY0x802, 0x817, 0x818, plus an inverse hint
Memory copy, set and compareDMA 0x813, 0x814, 0x816
EVM ADD, MUL, EXP, MOD0x811 for ADD, 0x801 for MUL and EXP, 0x802 for MOD

RIPEMD160, IDENTITY and MODEXP with operands over 32 bytes stay in software. DIV, SDIV and SMOD use a division hint that the guest checks.

Hints deserve a closer look. A hint, or fcall, returns a value the prover supplies freely, so the guest checks every hint before it uses the result. A bad inverse, square-root or division hint halts the run with an error, and no proof can exist. The one exception is a bad GLV-split hint: the guest just falls back to the software split, which needs no hint.

Further reading​