lib

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

commit a24ff9dcc23bc685c37c43593c7bc4b4a20085f5
parent 5d3377fa895865fae5ae14afea5dbb0122b0effd
Author: triesap <tyson@radroots.org>
Date:   Wed,  1 Jul 2026 07:32:43 +0000

trade: add validation trust contract

- add shared authority and confidence enums for trade validation receipts
- pin snake-case serde labels and parser helpers with tests
- keep the contract neutral with no SP1 dependency changes
- validate with radroots_trade fmt, test, and check lanes

Diffstat:
Mcrates/trade/src/validation_receipt.rs | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 147 insertions(+), 0 deletions(-)

diff --git a/crates/trade/src/validation_receipt.rs b/crates/trade/src/validation_receipt.rs @@ -64,6 +64,74 @@ pub enum RadrootsValidationReceiptResult { #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] +pub enum RadrootsTradeValidationAuthority { + DevDeterministicOnly, + TrustedRhiServiceKey, + CryptographicProofVerified, + TrustedServiceAndProofVerified, +} + +impl RadrootsTradeValidationAuthority { + pub const fn as_str(self) -> &'static str { + match self { + Self::DevDeterministicOnly => "dev_deterministic_only", + Self::TrustedRhiServiceKey => "trusted_rhi_service_key", + Self::CryptographicProofVerified => "cryptographic_proof_verified", + Self::TrustedServiceAndProofVerified => "trusted_service_and_proof_verified", + } + } + + pub fn from_label(value: &str) -> Option<Self> { + match value { + "dev_deterministic_only" => Some(Self::DevDeterministicOnly), + "trusted_rhi_service_key" => Some(Self::TrustedRhiServiceKey), + "cryptographic_proof_verified" => Some(Self::CryptographicProofVerified), + "trusted_service_and_proof_verified" => Some(Self::TrustedServiceAndProofVerified), + _ => None, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum RadrootsTradeCommitmentConfidence { + LocalOnly, + PendingRhi, + CommittedByTrustedService, + CommittedByCryptographicProof, + CommittedByTrustedServiceAndProof, + Invalid, +} + +impl RadrootsTradeCommitmentConfidence { + pub const fn as_str(self) -> &'static str { + match self { + Self::LocalOnly => "local_only", + Self::PendingRhi => "pending_rhi", + Self::CommittedByTrustedService => "committed_by_trusted_service", + Self::CommittedByCryptographicProof => "committed_by_cryptographic_proof", + Self::CommittedByTrustedServiceAndProof => "committed_by_trusted_service_and_proof", + Self::Invalid => "invalid", + } + } + + pub fn from_label(value: &str) -> Option<Self> { + match value { + "local_only" => Some(Self::LocalOnly), + "pending_rhi" => Some(Self::PendingRhi), + "committed_by_trusted_service" => Some(Self::CommittedByTrustedService), + "committed_by_cryptographic_proof" => Some(Self::CommittedByCryptographicProof), + "committed_by_trusted_service_and_proof" => { + Some(Self::CommittedByTrustedServiceAndProof) + } + "invalid" => Some(Self::Invalid), + _ => None, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] pub enum RadrootsValidationReceiptProofSystem { None, Sp1Core, @@ -695,6 +763,7 @@ fn zero_error_bitmap() -> &'static str { #[cfg(test)] mod tests { use super::{ + RadrootsTradeCommitmentConfidence, RadrootsTradeValidationAuthority, RadrootsTradeValidationReceipt, RadrootsValidationReceiptError, RadrootsValidationReceiptExpectedBinding, RadrootsValidationReceiptProof, RadrootsValidationReceiptProofSystem, RadrootsValidationReceiptResult, @@ -1418,6 +1487,84 @@ mod tests { } #[test] + fn validation_authority_contract_uses_stable_snake_case_labels() { + for (authority, label) in [ + ( + RadrootsTradeValidationAuthority::DevDeterministicOnly, + "dev_deterministic_only", + ), + ( + RadrootsTradeValidationAuthority::TrustedRhiServiceKey, + "trusted_rhi_service_key", + ), + ( + RadrootsTradeValidationAuthority::CryptographicProofVerified, + "cryptographic_proof_verified", + ), + ( + RadrootsTradeValidationAuthority::TrustedServiceAndProofVerified, + "trusted_service_and_proof_verified", + ), + ] { + assert_eq!(authority.as_str(), label); + assert_eq!( + RadrootsTradeValidationAuthority::from_label(label), + Some(authority) + ); + assert_eq!( + serde_json::to_string(&authority).expect("serialize authority"), + format!("\"{label}\"") + ); + assert_eq!( + serde_json::from_str::<RadrootsTradeValidationAuthority>(&format!("\"{label}\"")) + .expect("deserialize authority"), + authority + ); + } + assert_eq!(RadrootsTradeValidationAuthority::from_label("legacy"), None); + } + + #[test] + fn commitment_confidence_contract_uses_stable_snake_case_labels() { + for (confidence, label) in [ + (RadrootsTradeCommitmentConfidence::LocalOnly, "local_only"), + (RadrootsTradeCommitmentConfidence::PendingRhi, "pending_rhi"), + ( + RadrootsTradeCommitmentConfidence::CommittedByTrustedService, + "committed_by_trusted_service", + ), + ( + RadrootsTradeCommitmentConfidence::CommittedByCryptographicProof, + "committed_by_cryptographic_proof", + ), + ( + RadrootsTradeCommitmentConfidence::CommittedByTrustedServiceAndProof, + "committed_by_trusted_service_and_proof", + ), + (RadrootsTradeCommitmentConfidence::Invalid, "invalid"), + ] { + assert_eq!(confidence.as_str(), label); + assert_eq!( + RadrootsTradeCommitmentConfidence::from_label(label), + Some(confidence) + ); + assert_eq!( + serde_json::to_string(&confidence).expect("serialize confidence"), + format!("\"{label}\"") + ); + assert_eq!( + serde_json::from_str::<RadrootsTradeCommitmentConfidence>(&format!("\"{label}\"")) + .expect("deserialize confidence"), + confidence + ); + } + assert_eq!( + RadrootsTradeCommitmentConfidence::from_label("legacy"), + None + ); + } + + #[test] fn validation_receipt_public_values_hash_uses_domain_separator() { assert_ne!( validation_receipt_public_values_hash_hex(br#"{"schema_version":1}"#),