pub struct ProofEnvelope {
pub statement_kind: ProofStatementKind,
pub backend_id: BackendId,
pub version: u32,
pub public_inputs: Vec<Vec<u8>>,
pub commitment_roots: Vec<Hash256>,
pub verifier_key_or_image_id: Vec<u8>,
pub domain_separator: Vec<u8>,
}Expand description
A versioned envelope binding everything a verifier needs to know about a proof, independent of the proof bytes themselves.
Field order mirrors the VCG-001 “Next red test” bullet: “statement kind, backend id, version, public inputs, commitment roots, verifier key or image id, and domain separator.”
Fields§
§statement_kind: ProofStatementKindWhich kind of statement this envelope attests to.
backend_id: BackendIdWhich backend produced (and must verify) the wrapped proof.
version: u32Envelope format version. Independent of the crate/package version; bump when the envelope’s own field shape changes.
public_inputs: Vec<Vec<u8>>Public inputs to the statement, as opaque byte strings. Semantics
are defined per ProofStatementKind / backend.
commitment_roots: Vec<Hash256>Commitment roots (e.g. DAG roots, state roots) the statement is anchored to.
verifier_key_or_image_id: Vec<u8>The verifier key (SNARK/STARK) or image id (zkVM-style backends) needed to verify the wrapped proof, as opaque bytes.
domain_separator: Vec<u8>Domain separator binding this envelope to its intended context, so a valid proof for one domain cannot be replayed as valid for another.
Implementations§
Source§impl ProofEnvelope
impl ProofEnvelope
Sourcepub fn validate_backend(&self) -> Result<()>
pub fn validate_backend(&self) -> Result<()>
Validates that Self::backend_id names a known, registered
backend.
Fails closed: any BackendId::Unknown value — including ids that
happen to coincide with a future backend not yet registered here —
is refused. This must be called (directly, or transitively via
Self::verify) before any proof bytes wrapped by this envelope
are trusted.
Sourcepub fn binding_payload(&self) -> Result<Vec<u8>>
pub fn binding_payload(&self) -> Result<Vec<u8>>
Canonical journal-binding digest for a RISC Zero receipt (objective O-1.1, 2026-07-04 ratification slate).
Folds the ENTIRE envelope context — statement_kind, backend_id,
version, public_inputs, commitment_roots,
verifier_key_or_image_id, and domain_separator — into a single
BLAKE3 digest over canonical CBOR, under a fixed domain tag. This is the
value a RISC Zero receipt’s journal must commit to: the audited
RiscZeroReceiptVerifier checks the receipt verifies against the image
id AND that its journal equals this digest, so a receipt proven for one
(statement, roots, domain) context can never be replayed as valid under
another. Before O-1.1 the seam received only the image id and the raw
public inputs, dropping statement_kind, commitment_roots, and
domain_separator — an unbound statement.
§Errors
Returns ProofError::InvalidProofFormat if canonical CBOR encoding of
the binding tuple fails.
Canonical CBOR bytes hashed by Self::binding_digest.
A RISC Zero guest must commit exactly these bytes so
blake3(journal.bytes) equals the envelope binding digest.
pub fn binding_digest(&self) -> Result<Hash256>
Sourcepub fn verify(&self, receipt_bytes: &[u8]) -> Result<bool>
pub fn verify(&self, receipt_bytes: &[u8]) -> Result<bool>
Verifies the envelope’s named backend is both registered and, if unaudited, explicitly opted into.
receipt_bytes are the serialized risc0 Receipt/proof bytes to check
(objective O-1.2). They are threaded down to the
RiscZeroReceiptVerifier seam for the BackendId::RiscZero arm so
the future audited verifier can decode and check them; the
FailClosedRiscZeroVerifier default ignores them and still refuses.
The UnauditedBlake3Standin and Unknown arms never inspect
receipt_bytes — for them it is simply an unused parameter — so passing
any value (including &[]) cannot change their fail-closed outcomes.
No backend has a working, externally-reviewed verifier wired yet:
the unaudited blake3 stand-in is feature-gated and still a fail-closed
stub even when opted into (VCG-001a), and the RISC Zero seam
(VCG-001b, ratified decision D1) is wired but pending external
cryptographic review (see RiscZeroReceiptVerifier). Fail-closed:
every backend currently registered returns a typed error here —
there is no verifier wired for any backend at this stage. This is a
deliberate success-shaped surface trap avoidance: verify() must
never report Ok(true) unless it actually verified something.
Behavior:
- Unknown/unregistered backend id →
Err(ProofError::InvalidProofFormat)(fail-closed registry, checked first viaSelf::validate_backend). UNAUDITED_BLAKE3_STANDIN_BACKEND_ID→ first refuses withErr(ProofError::UnauditedImplementation)unless theunaudited-pedagogical-proofsfeature is enabled (mirroring [crate::guard_unaudited]); if that guard passes, still refuses withErr(ProofError::VerificationFailed)because no verifier is wired for this backend yet — construction/wrapping of an envelope for this backend is feature-gated as above, but verification is not implemented at all.BackendId::RiscZero→ always refuses withErr(ProofError::VerificationFailed)viaFailClosedRiscZeroVerifier, independent of theunaudited-pedagogical-proofsfeature flag (that flag only gates this crate’s own blake3 stand-in, not the RiscZero seam). The refusal reason names pending external review, not a missing feature opt-in.
Trait Implementations§
Source§impl Clone for ProofEnvelope
impl Clone for ProofEnvelope
Source§fn clone(&self) -> ProofEnvelope
fn clone(&self) -> ProofEnvelope
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ProofEnvelope
impl Debug for ProofEnvelope
Source§impl<'de> Deserialize<'de> for ProofEnvelope
impl<'de> Deserialize<'de> for ProofEnvelope
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for ProofEnvelope
Source§impl PartialEq for ProofEnvelope
impl PartialEq for ProofEnvelope
Source§impl Serialize for ProofEnvelope
impl Serialize for ProofEnvelope
impl StructuralPartialEq for ProofEnvelope
Auto Trait Implementations§
impl Freeze for ProofEnvelope
impl RefUnwindSafe for ProofEnvelope
impl Send for ProofEnvelope
impl Sync for ProofEnvelope
impl Unpin for ProofEnvelope
impl UnsafeUnpin for ProofEnvelope
impl UnwindSafe for ProofEnvelope
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more