Skip to main content

Claim

Struct Claim 

Source
pub struct Claim {
    pub data: String,
    pub metadata: Option<String>,
    pub timestamp: u64,
}
Expand description

A Claim representing a statement of truth to be anchored. Fields are ordered alphabetically to ensure “Canonical JSON” (JCS - RFC 8785) compliance when using deterministic serialization.

Fields§

§data: String

The actual data being claimed (e.g., “AI Model v1.0 Accuracy: 98%”)

§metadata: Option<String>

Optional metadata or context

§timestamp: u64

Timestamp of the claim (UTC seconds)

Implementations§

Source§

impl Claim

Source

pub fn new(data: String) -> Self

Create a new claim with the current system time (requires “std”)

Source

pub fn new_with_timestamp(data: String, timestamp: u64) -> Result<Self>

Create a new claim with a provided timestamp (useful for no-std)

Examples found in repository?
examples/generate_test_vectors.rs (line 14)
9fn main() {
10    println!("Generating cross-SDK test vectors...\n");
11
12    // Test Vector 1: Basic claim
13    let keypair1 = generate_keypair();
14    let claim1 = Claim::new_with_timestamp("test_data_123".to_string(), 1704067200).unwrap();
15    let signed1 = sign_claim(&claim1, &keypair1).unwrap();
16
17    let vector1 = json!({
18        "name": "basic_claim",
19        "description": "Basic claim with data and timestamp",
20        "public_key": hex::encode(keypair1.verifying_key().as_bytes()),
21        "claim": {
22            "data": claim1.data,
23            "timestamp": claim1.timestamp,
24        },
25        "canonical_json": r#"{"data":"test_data_123","timestamp":1704067200}"#,
26        "expected_signature": signed1.signature,
27    });
28
29    // Test Vector 2: Claim with metadata
30    let keypair2 = generate_keypair();
31    let mut claim2 = Claim::new_with_timestamp("hash_abc123".to_string(), 1704067200).unwrap();
32    claim2.metadata = Some("user_id:12345".to_string());
33    let signed2 = sign_claim(&claim2, &keypair2).unwrap();
34
35    let vector2 = json!({
36        "name": "claim_with_metadata",
37        "description": "Claim with optional metadata field",
38        "private_key": hex::encode(keypair2.to_bytes()),
39        "public_key": hex::encode(keypair2.verifying_key().as_bytes()),
40        "claim": {
41            "data": claim2.data,
42            "metadata": claim2.metadata,
43            "timestamp": claim2.timestamp,
44        },
45        "canonical_json": r#"{"data":"hash_abc123","metadata":"user_id:12345","timestamp":1704067200}"#,
46        "expected_signature": signed2.signature,
47    });
48
49    // Test Vector 3: Hash computation
50    let hash1 = compute_hash(b"hello");
51    let hash2 = compute_hash(b"");
52    let hash3 = compute_hash(b"Provncloud SDK");
53
54    let vector3 = json!({
55        "name": "hash_computation",
56        "description": "SHA-256 hash test vectors",
57        "test_cases": [
58            {
59                "input": "hello",
60                "expected_hash": hash1
61            },
62            {
63                "input": "",
64                "expected_hash": hash2
65            },
66            {
67                "input": "Provncloud SDK",
68                "expected_hash": hash3
69            }
70        ]
71    });
72
73    // Test Vector 4: Cross-sign test (same claim, different keys)
74    let keypair_a = generate_keypair();
75    let keypair_b = generate_keypair();
76    let claim_cross = Claim::new_with_timestamp("cross_test_data".to_string(), 1704067200).unwrap();
77
78    let signed_by_a = sign_claim(&claim_cross, &keypair_a).unwrap();
79    let signed_by_b = sign_claim(&claim_cross, &keypair_b).unwrap();
80
81    let vector4 = json!({
82        "name": "cross_sign_same_claim",
83        "description": "Same claim signed by two different keys",
84        "claim": {
85            "data": claim_cross.data,
86            "timestamp": claim_cross.timestamp,
87        },
88        "canonical_json": r#"{"data":"cross_test_data","timestamp":1704067200}"#,
89        "signatures": [
90            {
91                "signer": "key_a",
92                "private_key": hex::encode(keypair_a.to_bytes()),
93                "public_key": hex::encode(keypair_a.verifying_key().as_bytes()),
94                "signature": signed_by_a.signature
95            },
96            {
97                "signer": "key_b",
98                "private_key": hex::encode(keypair_b.to_bytes()),
99                "public_key": hex::encode(keypair_b.verifying_key().as_bytes()),
100                "signature": signed_by_b.signature
101            }
102        ]
103    });
104
105    // Combine all vectors
106    let test_vectors = json!({
107        "spec_version": "1.0",
108        "sdk_version": "0.2.0",
109        "generated_at": "2024-01-01T00:00:00Z",
110        "test_vectors": [
111            vector1,
112            vector2,
113            vector3,
114            vector4
115        ]
116    });
117
118    // Print as formatted JSON
119    println!("{}", serde_json::to_string_pretty(&test_vectors).unwrap());
120}
Source

pub fn to_signable_bytes(&self) -> Result<Vec<u8>>

Canonical serialization for signing (Sorted keys, no whitespace) This follows JCS (RFC 8785) logic by relying on struct field ordering.

Trait Implementations§

Source§

impl Clone for Claim

Source§

fn clone(&self) -> Claim

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Claim

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Claim

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for Claim

Source§

fn eq(&self, other: &Claim) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Claim

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Eq for Claim

Source§

impl StructuralPartialEq for Claim

Auto Trait Implementations§

§

impl Freeze for Claim

§

impl RefUnwindSafe for Claim

§

impl Send for Claim

§

impl Sync for Claim

§

impl Unpin for Claim

§

impl UnsafeUnpin for Claim

§

impl UnwindSafe for Claim

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,