mirror of
https://github.com/luxfi/p3q.git
synced 2026-11-02 14:41:48 +00:00
A STARK/FRI proof carries its own security parameters, and this verifier read them without ever asking whether they were enough: log_blowup and num_queries were range-checked in Header::decode and then never consulted as policy. Every point on the accepted grid verified, including log_blowup=1, num_queries=1 -- about one bit of query-phase soundness, two attempts to forge. Header::check_admissible is now the one place that decides, called from Header::decode for proofs off the wire and from the kernel for a ParsedProof assembled in memory. MIN_SOUNDNESS_BITS = 128, enforced as log_blowup * num_queries, which is an exact integer product under the capacity bound and so identical on every platform. A range check could not express it: the admissible region is bounded by a product, and no pair of per-field minimums draws that line. The floor would have bought nothing on its own. Folding is linear, so a prover who commits to an arbitrary word and folds it honestly satisfies every Merkle opening, every colinearity check and the final-polynomial evaluation -- a uniformly random word verified at 64 queries. The degree claim was never enforced anywhere: the ladder leaves 2^(log_final_poly - log_blowup) coefficients alive and the wire carries 2^log_final_poly of them, and nothing required the surplus to be zero. check_claimed_degree does, and the header now requires log_final_poly >= log_blowup so the ladder cannot run past degree 1. The toy prover grows prove_word, which commits to a word rather than to a polynomial -- the freedom an adversary has, and the only way to test that the degree bound is real. Golden vectors are regenerated at the cheapest admissible parameters (53 KB, up from 30 KB at 16 queries); every one of their 53,029 bytes is now shown to be load-bearing. What the floor does not fix: fold challenges come from the Goldilocks BASE field, and the proximity-gap term scales as N^2/|F|, so provable commit-phase soundness is at most 64 - 2*log_lde bits before constants. No query count moves that. LLM.md carries the numbers. Co-authored-by: Hanzo Dev <[email protected]>
144 lines
3.7 KiB
C
144 lines
3.7 KiB
C
// =============================================================================
|
|
// lux/p3q.h - P3Q strict-PQ verifier C ABI
|
|
// =============================================================================
|
|
//
|
|
// Generated by cbindgen from p3q-c-abi. DO NOT EDIT — regenerated on
|
|
// every build of the crate.
|
|
//
|
|
// Linkage: -lp3q (cdylib) on macOS/Linux
|
|
// -lp3q.lib on Windows
|
|
// Headers: /opt/homebrew/include/lux/p3q.h
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright (C) 2024-2026 Lux Industries Inc.
|
|
// =============================================================================
|
|
|
|
|
|
#ifndef LUX_P3Q_H
|
|
#define LUX_P3Q_H
|
|
|
|
// WARNING: regenerated by cbindgen — edits will be lost.
|
|
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
/**
|
|
* Verification succeeded — the proof is accepted.
|
|
*/
|
|
#define P3Q_OK 1
|
|
|
|
/**
|
|
* Verification ran to completion and rejected the proof.
|
|
*/
|
|
#define P3Q_REJECTED 0
|
|
|
|
/**
|
|
* One of the input pointer / length pairs was malformed
|
|
* (null pointer with non-zero length, etc).
|
|
*/
|
|
#define P3Q_ERR_NULL_PTR -1
|
|
|
|
/**
|
|
* The proof bytes did not decode into a well-formed protocol object.
|
|
*/
|
|
#define P3Q_ERR_PARSE -2
|
|
|
|
/**
|
|
* The proof's profile byte does not match a verifier the shim knows.
|
|
*/
|
|
#define P3Q_ERR_UNSUPPORTED_PROFILE -3
|
|
|
|
/**
|
|
* Merkle authentication failed.
|
|
*/
|
|
#define P3Q_ERR_MERKLE -4
|
|
|
|
/**
|
|
* FRI low-degree check failed.
|
|
*/
|
|
#define P3Q_ERR_FRI -5
|
|
|
|
/**
|
|
* STARK constraint check failed.
|
|
*/
|
|
#define P3Q_ERR_STARK -6
|
|
|
|
/**
|
|
* Fiat-Shamir transcript mismatch.
|
|
*/
|
|
#define P3Q_ERR_TRANSCRIPT -7
|
|
|
|
/**
|
|
* Field element out of range.
|
|
*/
|
|
#define P3Q_ERR_FIELD -8
|
|
|
|
/**
|
|
* Z-Chain circuit-level invariant failed.
|
|
*/
|
|
#define P3Q_ERR_CIRCUIT -9
|
|
|
|
/**
|
|
* A Rust panic was caught at the FFI boundary. This MUST be treated
|
|
* as a verification failure by the caller.
|
|
*/
|
|
#define P3Q_ERR_PANIC -99
|
|
|
|
/**
|
|
* Verify a P3Q proof.
|
|
*
|
|
* `public_input` is the public-input bytes the verifier binds against
|
|
* the Fiat-Shamir transcript. `proof` is the wire-level proof bytes
|
|
* (first byte = `ProofSystemId`, rest = profile-defined).
|
|
*
|
|
* Returns:
|
|
* * `P3Q_OK` (1) - proof accepted
|
|
* * `P3Q_REJECTED` (0) - proof rejected by the verifier
|
|
* * negative value - error (see `P3Q_ERR_*` constants)
|
|
*
|
|
* # Safety
|
|
* Caller MUST ensure the `(public_input, public_input_len)` and
|
|
* `(proof, proof_len)` pairs are valid `(ptr, len)` pairs: for any
|
|
* non-zero `len`, the pointer must be non-null and point to at least
|
|
* `len` initialized bytes. `len == 0` accepts a null pointer.
|
|
*/
|
|
int32_t p3q_verify(const uint8_t *public_input,
|
|
uintptr_t public_input_len,
|
|
const uint8_t *proof,
|
|
uintptr_t proof_len);
|
|
|
|
/**
|
|
* Return the on-wire byte for the P3Q-SHA3 profile (`0x10`). Useful
|
|
* for callers that want to construct probe proofs in C without
|
|
* hard-coding the magic number.
|
|
*/
|
|
uint8_t p3q_profile_sha3(void);
|
|
|
|
/**
|
|
* Return the on-wire byte for the P3Q-Keccak profile (`0x11`).
|
|
*/
|
|
uint8_t p3q_profile_keccak(void);
|
|
|
|
/**
|
|
* Query-phase soundness, in bits, that the linked verifier requires
|
|
* of a proof's `(log_blowup, num_queries)` before it will do any work.
|
|
*
|
|
* Exported so a caller enforcing the same floor ahead of the FFI —
|
|
* the Lux `starkfri` precompile does, to keep the policy legible in
|
|
* the chain's own code — can assert it agrees with the verifier it
|
|
* links, rather than carrying a second copy that drifts.
|
|
*/
|
|
uint32_t p3q_min_soundness_bits(void);
|
|
|
|
/**
|
|
* Semver string for the linked p3q-c-abi crate. Returns a static
|
|
* nul-terminated UTF-8 string. The caller must NOT free this pointer.
|
|
*/
|
|
const char *p3q_version(void);
|
|
|
|
#endif /* LUX_P3Q_H */
|