lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit 7d95721aaee0347fce2d05b9beb9024a6b96c664
parent b6559d3d19cf0f4d6384c3e305f4285d55e36a34
Author: triesap <tyson@radroots.org>
Date:   Wed,  3 Jun 2026 12:27:47 -0700

sp1_host_trade: report unavailable verifier from no-feature APIs

- add a typed host error for unavailable SP1 proof verification
- expose no-sp1 verification entry points that fail with that variant
- cover inline and resolved verification APIs in default-feature tests
- preserve verifier-enabled proof verification paths behind sp1_verify

Diffstat:
Mcrates/sp1_host_trade/src/lib.rs | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 96 insertions(+), 5 deletions(-)

diff --git a/crates/sp1_host_trade/src/lib.rs b/crates/sp1_host_trade/src/lib.rs @@ -372,6 +372,8 @@ pub enum RadrootsSp1TradeHostError { Sp1SetupFailed(String), #[error("SP1 proof generation failed: {0}")] Sp1ProofFailed(String), + #[error("SP1 proof verifier is unavailable in this build")] + Sp1ProofVerifierUnavailable, #[error("SP1 proof verification failed: {0}")] Sp1ProofVerificationFailed(String), #[error("SP1 proof material failed to decode: {0}")] @@ -654,6 +656,14 @@ pub async fn verify_order_acceptance_resolved_sp1_proof_artifact( Ok(()) } +#[cfg(not(feature = "sp1_verify"))] +pub async fn verify_order_acceptance_resolved_sp1_proof_artifact( + _execution: &RadrootsSp1TradePublicValuesExecution, + _resolved: &RadrootsSp1TradeResolvedProofArtifact, +) -> Result<(), RadrootsSp1TradeHostError> { + Err(RadrootsSp1TradeHostError::Sp1ProofVerifierUnavailable) +} + #[cfg(feature = "sp1_verify")] pub async fn verify_order_acceptance_validation_receipt_inline_sp1_proof( receipt: &RadrootsTradeValidationReceipt, @@ -731,6 +741,13 @@ pub async fn verify_order_acceptance_validation_receipt_inline_sp1_proof( }) } +#[cfg(not(feature = "sp1_verify"))] +pub async fn verify_order_acceptance_validation_receipt_inline_sp1_proof( + _receipt: &RadrootsTradeValidationReceipt, +) -> Result<RadrootsSp1TradeValidationReceiptVerification, RadrootsSp1TradeHostError> { + Err(RadrootsSp1TradeHostError::Sp1ProofVerifierUnavailable) +} + #[cfg(feature = "sp1_verify")] pub async fn verify_order_acceptance_validation_receipt_resolved_sp1_proof( receipt: &RadrootsTradeValidationReceipt, @@ -793,6 +810,14 @@ pub async fn verify_order_acceptance_validation_receipt_resolved_sp1_proof( }) } +#[cfg(not(feature = "sp1_verify"))] +pub async fn verify_order_acceptance_validation_receipt_resolved_sp1_proof( + _receipt: &RadrootsTradeValidationReceipt, + _resolved: &RadrootsSp1TradeResolvedProofArtifact, +) -> Result<RadrootsSp1TradeValidationReceiptVerification, RadrootsSp1TradeHostError> { + Err(RadrootsSp1TradeHostError::Sp1ProofVerifierUnavailable) +} + pub fn generate_order_acceptance_proof( witness: &RadrootsSp1TradeOrderAcceptanceWitness, mode: RadrootsSp1TradeProofMode, @@ -1699,12 +1724,10 @@ mod tests { RadrootsSp1TradeOrderDecisionWitness, RadrootsSp1TradeOrderItemWitness, RadrootsSp1TradeOrderRequestWitness, RadrootsSp1TradeProofResult, }; - #[cfg(feature = "sp1_verify")] - use radroots_trade::validation_receipt::RadrootsValidationReceiptProof; use radroots_trade::validation_receipt::{ - RadrootsValidationReceiptExpectedBinding, RadrootsValidationReceiptProofSystem, - RadrootsValidationReceiptResult, validation_receipt_event_build, - verify_validation_receipt_event, + RadrootsValidationReceiptExpectedBinding, RadrootsValidationReceiptProof, + RadrootsValidationReceiptProofSystem, RadrootsValidationReceiptResult, + validation_receipt_event_build, verify_validation_receipt_event, }; #[cfg(feature = "sp1_verify")] use serde::Deserialize; @@ -2057,6 +2080,74 @@ mod tests { .expect("referenced artifact is structurally valid"); } + #[cfg(not(feature = "sp1_verify"))] + #[test] + fn sp1_verification_apis_report_unavailable_without_sp1_verify_feature() { + let runtime = tokio::runtime::Runtime::new().expect("runtime"); + runtime.block_on(async { + let bundle = + generate_order_acceptance_proof(&witness(), RadrootsSp1TradeProofMode::None) + .expect("proof bundle"); + let mut inline_receipt = + validation_receipt_for_order_acceptance_proof(&bundle).expect("validation receipt"); + inline_receipt.proof = RadrootsValidationReceiptProof { + inline_proof_base64: Some("cHJvb2Y=".to_string()), + mode: Some("core".to_string()), + program_hash: Some( + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + .to_string(), + ), + proof_reference: None, + system: RadrootsValidationReceiptProofSystem::Sp1Core, + verifying_key_hash: Some( + "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + .to_string(), + ), + }; + let err = + super::verify_order_acceptance_validation_receipt_inline_sp1_proof(&inline_receipt) + .await + .expect_err("verifier unavailable"); + assert_eq!(err, RadrootsSp1TradeHostError::Sp1ProofVerifierUnavailable); + + let execution = + super::execute_order_acceptance_public_values(&witness()).expect("execution"); + let artifact = super::referenced_order_acceptance_proof_artifact_for_execution( + &execution, + RadrootsSp1TradeProofMode::Core, + format!("radroots-proof://sha256/{}", "1".repeat(64)), + ) + .expect("referenced artifact"); + let resolved = super::RadrootsSp1TradeResolvedProofArtifact { + artifact: artifact.clone(), + resolved_proof_envelope_base64: None, + }; + let err = + super::verify_order_acceptance_resolved_sp1_proof_artifact(&execution, &resolved) + .await + .expect_err("verifier unavailable"); + assert_eq!(err, RadrootsSp1TradeHostError::Sp1ProofVerifierUnavailable); + + let mut referenced_receipt = + validation_receipt_for_order_acceptance_proof(&bundle).expect("validation receipt"); + referenced_receipt.proof = RadrootsValidationReceiptProof { + inline_proof_base64: artifact.inline_proof_base64.clone(), + mode: artifact.mode.clone(), + program_hash: artifact.program_hash.clone(), + proof_reference: artifact.proof_reference.clone(), + system: artifact.system, + verifying_key_hash: artifact.verifying_key_hash.clone(), + }; + let err = super::verify_order_acceptance_validation_receipt_resolved_sp1_proof( + &referenced_receipt, + &resolved, + ) + .await + .expect_err("verifier unavailable"); + assert_eq!(err, RadrootsSp1TradeHostError::Sp1ProofVerifierUnavailable); + }); + } + #[test] fn remote_prover_contract_round_trips_provider_neutral_payloads() { let request = super::RadrootsSp1TradeRemoteProverRequest {