mirror of
https://github.com/luxfi/node.git
synced 2026-10-30 15:24:05 +00:00
The C++ chains carried four copies of the ZAP runtime — quantumvm, zkvm, dexvm, and a chain-neutral one under chains/cpp/zap that fhevm read. Two of them were the neutral copy minus a pair of signed-integer helpers; quantumvm's was a separate rewrite with int64 offsets and an optional returned from parse. Nothing about a codec is per-chain, so nothing about it should have been written down five times. They now read the published zap-proto/cpp, which platformvm and xvm already did, pinned in chains/cpp/zap.cmake. 2,198 lines deleted. The renames were mechanical (get_/put_ became load_/store_, len became size, bytes_fixed_slice became bytes_fixed, parse returns an expected instead of filling out-parameters). Two are worth naming: the published runtime has no set_i64/i64, because the wire has no signed type, so the F-chain's block timestamp is written and read through a cast — the same eight bytes, said by the caller instead of by the codec. And the pointer list keeps its count from finish() rather than a separate offset(). One behavioural difference between the copies and the published runtime was checked rather than assumed: a byte tail is appended immediately by the copies and at finish() by the published one. Those differ only if a builder advances the cursor between setting a tail and finishing the object, and no builder in the tree does — every one writes its payloads, opens its object, sets its fields, and finishes. Green on the published runtime: zkvm 14/14, dexvm 10/10, fhevm 14/14, quantumvm 13/13, wire golden tests included.
188 lines
7.9 KiB
CMake
188 lines
7.9 KiB
CMake
# Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
|
# SPDX-License-Identifier: BSD-3-Clause-Eco
|
|
#
|
|
# zkvm — the Lux Z-Chain (shielded UTXO settlement) in C++, behind the node's VM
|
|
# seam.
|
|
#
|
|
# Layering, each layer below REUSED unmodified:
|
|
#
|
|
# luxcpp/crypto sha256, and the first-party bn254 tower + optimal-ate
|
|
# pairing the classical proof path is judged by
|
|
# lux-cpp/consensus the Id type the seam speaks (header-only here)
|
|
# lux-cpp/node include/lux/node/vm.hpp — the VM seam itself
|
|
# ─────────────────────────── NEW in zkvm ────────────────────────────
|
|
# zap-proto/cpp the ZAP protocol SDK (published, pinned in zap.cmake)
|
|
# wire the canonical/agreement rules every frame is held to
|
|
# txs the shielded transaction and the identity it is decided by
|
|
# store the durable map, and the view a decision writes through
|
|
# utxo the shielded outputs
|
|
# nullifier the spent set
|
|
# root the state root a validator signs
|
|
# mempool what is pending, and the order a proposer takes it in
|
|
# starkfri the strict-PQ STARK/FRI verification seam
|
|
# groth16 the classical proof system's encoding and point discipline
|
|
# verifier the profile gate and the proof cache
|
|
# chainstore how a decision becomes fact
|
|
# block the linear block
|
|
# vertex the DAG shape
|
|
# vm the seam implementation
|
|
#
|
|
# Reused, NOT vendored. The checkouts are found where they actually sit;
|
|
# -DLUXCPP_CRYPTO_DIR / -DNODE_DIR / -DCONSENSUS_DIR override.
|
|
|
|
cmake_minimum_required(VERSION 3.20)
|
|
project(zkvm LANGUAGES CXX)
|
|
|
|
|
|
# The wire this chain speaks comes from the published SDK, not from here.
|
|
include(${CMAKE_CURRENT_SOURCE_DIR}/../zap.cmake)
|
|
|
|
set(CMAKE_CXX_STANDARD 23)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
if(NOT CMAKE_BUILD_TYPE)
|
|
set(CMAKE_BUILD_TYPE Release)
|
|
endif()
|
|
|
|
set(ZKVM_SANITIZE "" CACHE STRING "Sanitizer for zkvm's own code (e.g. address,undefined)")
|
|
|
|
# find_checkout(VAR MARKER candidate...) — first candidate holding MARKER wins.
|
|
# The marker is a FILE, not a directory name, because names are ambiguous here:
|
|
# `consensus` beside node in the lux checkout is the GO implementation, and only
|
|
# the header tells the two apart.
|
|
function(find_checkout out marker)
|
|
foreach(_root ${ARGN})
|
|
get_filename_component(_abs "${_root}" ABSOLUTE)
|
|
if(EXISTS "${_abs}/${marker}")
|
|
set(${out} "${_abs}" PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
endforeach()
|
|
set(${out} "${out}-NOTFOUND" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
find_checkout(_crypto "bn254/cpp/bn254_pairing.hpp"
|
|
"${LUXCPP_CRYPTO_DIR}"
|
|
"$ENV{HOME}/work/luxcpp/crypto"
|
|
"${CMAKE_SOURCE_DIR}/../../../../luxcpp/crypto")
|
|
if(NOT _crypto)
|
|
message(FATAL_ERROR
|
|
"luxcpp/crypto not found (looked for bn254/cpp/bn254_pairing.hpp). "
|
|
"Pass -DLUXCPP_CRYPTO_DIR=/path/to/luxcpp/crypto.")
|
|
endif()
|
|
message(STATUS "zkvm: reusing crypto at ${_crypto}")
|
|
|
|
find_checkout(_node "include/lux/node/vm.hpp"
|
|
"${NODE_DIR}"
|
|
"$ENV{HOME}/work/lux-cpp/node"
|
|
"${CMAKE_SOURCE_DIR}/../../../../lux-cpp/node")
|
|
find_checkout(_consensus "include/lux/consensus/quorum_cert_engine.hpp"
|
|
"${CONSENSUS_DIR}"
|
|
"$ENV{HOME}/work/lux-cpp/consensus"
|
|
"${CMAKE_SOURCE_DIR}/../../../../lux-cpp/consensus")
|
|
|
|
# The seam is the point of the port, so its absence is a hard error rather than
|
|
# a quiet feature-off: a chain built against no seam is a library nothing runs.
|
|
if(NOT _node OR NOT _consensus)
|
|
message(FATAL_ERROR
|
|
"the VM seam was not found — node=${_node} consensus=${_consensus}. "
|
|
"Pass -DNODE_DIR=/path/to/lux-cpp/node -DCONSENSUS_DIR=/path/to/lux-cpp/consensus.")
|
|
endif()
|
|
message(STATUS "zkvm: VM seam at ${_node}, Id from ${_consensus}")
|
|
|
|
# ── the reused crypto, compiled in place (no vendoring, no submodule) ────────
|
|
#
|
|
# sha256 is the chain's ONE hash. bn254 is the curve the classical proof path is
|
|
# judged on — and the ONLY compiled unit it needs, the rest of the tower being
|
|
# header-only.
|
|
add_library(zkvm_crypto STATIC
|
|
${_crypto}/sha256/cpp/sha256.cpp
|
|
${_crypto}/bn254/cpp/bn254_pairing.cpp
|
|
)
|
|
target_include_directories(zkvm_crypto PUBLIC
|
|
${_crypto}/include
|
|
${_crypto}/sha256/cpp
|
|
${_crypto}/bn254/cpp
|
|
)
|
|
|
|
# ── zkvm itself ──────────────────────────────────────────────────────────────
|
|
add_library(zkvm STATIC
|
|
src/id.cpp
|
|
src/txs.cpp
|
|
src/store.cpp
|
|
src/utxo.cpp
|
|
src/nullifier.cpp
|
|
src/root.cpp
|
|
src/mempool.cpp
|
|
src/starkfri.cpp
|
|
src/groth16.cpp
|
|
src/verifier.cpp
|
|
src/chainstore.cpp
|
|
src/block.cpp
|
|
src/vertex.cpp
|
|
src/vm.cpp
|
|
)
|
|
target_include_directories(zkvm PUBLIC
|
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
|
${_node}/include
|
|
${_consensus}/include
|
|
)
|
|
target_link_libraries(zkvm PUBLIC zap::zap zkvm_crypto)
|
|
target_compile_options(zkvm PRIVATE -Wall -Wextra)
|
|
find_package(Threads REQUIRED)
|
|
target_link_libraries(zkvm PUBLIC Threads::Threads)
|
|
|
|
# ── tests ────────────────────────────────────────────────────────────────────
|
|
# golden the bytes, the ids and the roots, against the GO Z-Chain's own
|
|
# wire canonicality and the length/blob agreement rule
|
|
# txs the identity, and every field it commits to
|
|
# groth16 point encodings, the field, and the pairing verdict
|
|
# verifier the classical path's refusals and its one acceptance
|
|
# tamper proofs that DECODE and are still not proofs of this statement —
|
|
# the verdicts only the pairing can reach
|
|
# strictpq the profile gate: what a strict-PQ chain will and will not judge
|
|
# starkfri the strict-PQ seam: unbound refuses, bound decides
|
|
# store the durable log, the view, and what survives a restart
|
|
# state the spent set, the UTXO set and the root
|
|
# mempool admission, eviction, ordering and expiry
|
|
# block verify → accept → reject over the node's seam
|
|
# vertex the DAG shape, its conflicts and its wire
|
|
# vm the whole chain: genesis, build, verify, accept, restart
|
|
enable_testing()
|
|
set(ZKVM_TESTS golden wire txs groth16 verifier tamper strictpq starkfri store state mempool block
|
|
vertex vm)
|
|
foreach(_t ${ZKVM_TESTS})
|
|
add_executable(${_t}_test test/${_t}_test.cpp)
|
|
target_link_libraries(${_t}_test PRIVATE zkvm)
|
|
target_include_directories(${_t}_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test)
|
|
target_compile_options(${_t}_test PRIVATE -Wall -Wextra)
|
|
add_test(NAME ${_t} COMMAND ${_t}_test)
|
|
endforeach()
|
|
|
|
# ── the differential evaluator ───────────────────────────────────────────────
|
|
#
|
|
# Not a test: it reads the shared corpus and PRINTS this chain's answers, and
|
|
# `make chains` compares them against the Go Z-chain's. It is built here so a
|
|
# chain that stopped answering is a build failure rather than a silently
|
|
# missing voice.
|
|
add_executable(zkvm_conformance test/conformance.cpp)
|
|
target_link_libraries(zkvm_conformance PRIVATE zkvm)
|
|
# The corpus format, the verdict words and the error-word table are shared with
|
|
# every other C++ evaluator, because a table that differed between two of them
|
|
# reported its own difference as a chain's.
|
|
target_include_directories(zkvm_conformance PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../conformance/include)
|
|
target_compile_options(zkvm_conformance PRIVATE -Wall -Wextra)
|
|
|
|
if(ZKVM_SANITIZE)
|
|
set(_san -fsanitize=${ZKVM_SANITIZE} -fno-omit-frame-pointer)
|
|
set(_targets zkvm zkvm_conformance)
|
|
foreach(_t ${ZKVM_TESTS})
|
|
list(APPEND _targets ${_t}_test)
|
|
endforeach()
|
|
foreach(_t ${_targets})
|
|
target_compile_options(${_t} PRIVATE ${_san})
|
|
target_link_options(${_t} PRIVATE ${_san})
|
|
endforeach()
|
|
endif()
|