• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

input-output-hk / catalyst-libs / 15197629872

22 May 2025 09:57PM UTC coverage: 65.69% (+0.08%) from 65.61%
15197629872

Pull #345

github

web-flow
Merge edbc1a4b4 into b9d9c4fe6
Pull Request #345: fix(rust/signed-doc): Preserve original `raw_bytes`

20 of 22 new or added lines in 2 files covered. (90.91%)

1 existing line in 1 file now uncovered.

10965 of 16692 relevant lines covered (65.69%)

2438.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.36
/rust/signed_doc/src/builder.rs
1
//! Catalyst Signed Document Builder.
2
use catalyst_types::{catalyst_id::CatalystId, problem_report::ProblemReport};
3

4
use crate::{
5
    signature::Signature, CatalystSignedDocument, Content, InnerCatalystSignedDocument, Metadata,
6
    Signatures, PROBLEM_REPORT_CTX,
7
};
8

9
/// Catalyst Signed Document Builder.
10
#[derive(Debug)]
11
pub struct Builder(InnerCatalystSignedDocument);
12

13
impl Default for Builder {
14
    fn default() -> Self {
×
15
        Self::new()
×
16
    }
×
17
}
18

19
impl Builder {
20
    /// Start building a signed document
21
    #[must_use]
22
    pub fn new() -> Self {
104✔
23
        let report = ProblemReport::new(PROBLEM_REPORT_CTX);
104✔
24
        Self(InnerCatalystSignedDocument {
104✔
25
            report,
104✔
26
            metadata: Metadata::default(),
104✔
27
            content: Content::default(),
104✔
28
            signatures: Signatures::default(),
104✔
29
            raw_bytes: None,
104✔
30
        })
104✔
31
    }
104✔
32

33
    /// Set document metadata in JSON format
34
    /// Collect problem report if some fields are missing.
35
    ///
36
    /// # Errors
37
    /// - Fails if it is invalid metadata fields JSON object.
38
    pub fn with_json_metadata(mut self, json: serde_json::Value) -> anyhow::Result<Self> {
88✔
39
        let metadata = serde_json::from_value(json)?;
88✔
40
        self.0.metadata = Metadata::from_metadata_fields(metadata, &self.0.report);
88✔
41
        Ok(self)
88✔
42
    }
88✔
43

44
    /// Set decoded (original) document content bytes
45
    #[must_use]
46
    pub fn with_decoded_content(mut self, content: Vec<u8>) -> Self {
49✔
47
        self.0.content = Content::from_decoded(content);
49✔
48
        self
49✔
49
    }
49✔
50

51
    /// Add a signature to the document
52
    ///
53
    /// # Errors
54
    ///
55
    /// Fails if a `CatalystSignedDocument` cannot be created due to missing metadata or
56
    /// content, due to malformed data, or when the signed document cannot be
57
    /// converted into `coset::CoseSign`.
58
    pub fn add_signature(
18✔
59
        mut self, sign_fn: impl FnOnce(Vec<u8>) -> Vec<u8>, kid: &CatalystId,
18✔
60
    ) -> anyhow::Result<Self> {
18✔
61
        let cose_sign = self
18✔
62
            .0
18✔
63
            .as_cose_sign()
18✔
64
            .map_err(|e| anyhow::anyhow!("Failed to sign: {e}"))?;
18✔
65

66
        let protected_header = coset::HeaderBuilder::new().key_id(kid.to_string().into_bytes());
18✔
67

18✔
68
        let mut signature = coset::CoseSignatureBuilder::new()
18✔
69
            .protected(protected_header.build())
18✔
70
            .build();
18✔
71
        let data_to_sign = cose_sign.tbs_data(&[], &signature);
18✔
72
        signature.signature = sign_fn(data_to_sign);
18✔
73
        if let Some(sign) = Signature::from_cose_sig(signature, &self.0.report) {
18✔
74
            self.0.signatures.push(sign);
17✔
75
        }
17✔
76

77
        Ok(self)
18✔
78
    }
18✔
79

80
    /// Build a signed document with the collected error report.
81
    /// Could provide an invalid document.
82
    #[must_use]
83
    pub fn build(self) -> CatalystSignedDocument {
104✔
84
        self.0.into()
104✔
85
    }
104✔
86
}
87

88
impl From<&CatalystSignedDocument> for Builder {
89
    fn from(value: &CatalystSignedDocument) -> Self {
×
90
        Self(InnerCatalystSignedDocument {
×
91
            metadata: value.inner.metadata.clone(),
×
92
            content: value.inner.content.clone(),
×
93
            signatures: value.inner.signatures.clone(),
×
94
            report: value.inner.report.clone(),
×
NEW
95
            raw_bytes: None,
×
96
        })
×
97
    }
×
98
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc