Skip to content

Commit 128a800

Browse files
committed
fix(rust/signed_doc): use minicbor encode/decode
* wip: fix examples
1 parent e81df07 commit 128a800

File tree

5 files changed

+165
-134
lines changed

5 files changed

+165
-134
lines changed

rust/signed_doc/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ workspace = true
1212

1313
[dependencies]
1414
cardano-blockchain-types = { version = "0.0.1", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.11" }
15-
catalyst-types = { version = "0.0.1", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250112-00" }
15+
catalyst-types = { version = "0.0.1", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250114-01" }
1616
anyhow = "1.0.95"
1717
serde = { version = "1.0.217", features = ["derive"] }
1818
serde_json = "1.0.134"
1919
# TODO: Bump this to the latest version and fix the code
2020
jsonschema = "0.18.3"
2121
coset = "0.3.8"
22+
minicbor = "0.25.1"
2223
brotli = "7.0.0"
2324
ed25519-dalek = { version = "2.1.1", features = ["pem", "rand_core"] }
2425
uuid = { version = "1.11.0", features = ["v4", "v7", "serde"] }

rust/signed_doc/examples/mk_signed_doc.rs

Lines changed: 91 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{
88
path::PathBuf,
99
};
1010

11-
use catalyst_signed_doc::{DocumentRef, KidUri, Metadata, UuidV7};
11+
use catalyst_signed_doc::{DocumentRef, KidUri, Metadata};
1212
use clap::Parser;
1313
use coset::{iana::CoapContentFormat, CborSerializable};
1414
use ed25519_dalek::{
@@ -68,7 +68,7 @@ fn encode_cbor_uuid(uuid: &uuid::Uuid) -> coset::cbor::Value {
6868
)
6969
}
7070

71-
fn decode_cbor_uuid(val: &coset::cbor::Value) -> anyhow::Result<uuid::Uuid> {
71+
fn _decode_cbor_uuid(val: &coset::cbor::Value) -> anyhow::Result<uuid::Uuid> {
7272
let Some((UUID_CBOR_TAG, coset::cbor::Value::Bytes(bytes))) = val.as_tag() else {
7373
anyhow::bail!("Invalid CBOR encoded UUID type");
7474
};
@@ -94,18 +94,8 @@ fn _encode_cbor_document_ref(doc_ref: &DocumentRef) -> coset::cbor::Value {
9494
}
9595

9696
#[allow(clippy::indexing_slicing)]
97-
fn decode_cbor_document_ref(val: &coset::cbor::Value) -> anyhow::Result<DocumentRef> {
98-
if let Ok(id) = UuidV7::try_from(val) {
99-
Ok(DocumentRef::Latest { id })
100-
} else {
101-
let Some(array) = val.as_array() else {
102-
anyhow::bail!("Invalid CBOR encoded document `ref` type");
103-
};
104-
anyhow::ensure!(array.len() == 2, "Invalid CBOR encoded document `ref` type");
105-
let id = UuidV7::try_from(&array[0])?;
106-
let ver = UuidV7::try_from(&array[1])?;
107-
Ok(DocumentRef::WithVer { id, ver })
108-
}
97+
fn _decode_cbor_document_ref(val: &coset::cbor::Value) -> anyhow::Result<DocumentRef> {
98+
DocumentRef::try_from(val)
10999
}
110100

111101
impl Cli {
@@ -227,7 +217,7 @@ fn build_empty_cose_doc(doc_bytes: Vec<u8>, meta: &Metadata) -> coset::CoseSign
227217
coset::Label::Text("ver".to_string()),
228218
encode_cbor_uuid(&meta.doc_ver()),
229219
));
230-
let meta_rest = meta.extra().header_rest();
220+
let meta_rest = meta.extra().header_rest().unwrap_or_default();
231221

232222
if !meta_rest.is_empty() {
233223
protected_header.rest.extend(meta_rest);
@@ -336,89 +326,92 @@ fn validate_cose_protected_header(cose: &coset::CoseSign) -> anyhow::Result<()>
336326
"Invalid COSE document protected header"
337327
);
338328

339-
let Some((_, value)) = cose
340-
.protected
341-
.header
342-
.rest
343-
.iter()
344-
.find(|(key, _)| key == &coset::Label::Text("type".to_string()))
345-
else {
346-
anyhow::bail!("Invalid COSE protected header, missing `type` field");
347-
};
348-
decode_cbor_uuid(value)
349-
.map_err(|e| anyhow::anyhow!("Invalid COSE protected header `type` field, err: {e}"))?;
350-
351-
let Some((_, value)) = cose
352-
.protected
353-
.header
354-
.rest
355-
.iter()
356-
.find(|(key, _)| key == &coset::Label::Text("id".to_string()))
357-
else {
358-
anyhow::bail!("Invalid COSE protected header, missing `id` field");
359-
};
360-
decode_cbor_uuid(value)
361-
.map_err(|e| anyhow::anyhow!("Invalid COSE protected header `id` field, err: {e}"))?;
362-
363-
let Some((_, value)) = cose
364-
.protected
365-
.header
366-
.rest
367-
.iter()
368-
.find(|(key, _)| key == &coset::Label::Text("ver".to_string()))
369-
else {
370-
anyhow::bail!("Invalid COSE protected header, missing `ver` field");
371-
};
372-
decode_cbor_uuid(value)
373-
.map_err(|e| anyhow::anyhow!("Invalid COSE protected header `ver` field, err: {e}"))?;
374-
375-
if let Some((_, value)) = cose
376-
.protected
377-
.header
378-
.rest
379-
.iter()
380-
.find(|(key, _)| key == &coset::Label::Text("ref".to_string()))
381-
{
382-
decode_cbor_document_ref(value)
383-
.map_err(|e| anyhow::anyhow!("Invalid COSE protected header `ref` field, err: {e}"))?;
384-
}
385-
386-
if let Some((_, value)) = cose
387-
.protected
388-
.header
389-
.rest
390-
.iter()
391-
.find(|(key, _)| key == &coset::Label::Text("template".to_string()))
392-
{
393-
decode_cbor_document_ref(value).map_err(|e| {
394-
anyhow::anyhow!("Invalid COSE protected header `template` field, err: {e}")
395-
})?;
396-
}
397-
398-
if let Some((_, value)) = cose
399-
.protected
400-
.header
401-
.rest
402-
.iter()
403-
.find(|(key, _)| key == &coset::Label::Text("reply".to_string()))
404-
{
405-
decode_cbor_document_ref(value).map_err(|e| {
406-
anyhow::anyhow!("Invalid COSE protected header `reply` field, err: {e}")
407-
})?;
408-
}
409-
410-
if let Some((_, value)) = cose
411-
.protected
412-
.header
413-
.rest
414-
.iter()
415-
.find(|(key, _)| key == &coset::Label::Text("section".to_string()))
416-
{
417-
anyhow::ensure!(
418-
value.is_text(),
419-
"Invalid COSE protected header, missing `section` field"
420-
);
421-
}
329+
// let Some((_, value)) = cose
330+
// .protected
331+
// .header
332+
// .rest
333+
// .iter()
334+
// .find(|(key, _)| key == &coset::Label::Text("type".to_string()))
335+
// else {
336+
// anyhow::bail!("Invalid COSE protected header, missing `type` field");
337+
// };
338+
// decode_cbor_uuid(value)
339+
// .map_err(|e| anyhow::anyhow!("Invalid COSE protected header `type` field, err:
340+
// {e}"))?;
341+
342+
// let Some((_, value)) = cose
343+
// .protected
344+
// .header
345+
// .rest
346+
// .iter()
347+
// .find(|(key, _)| key == &coset::Label::Text("id".to_string()))
348+
// else {
349+
// anyhow::bail!("Invalid COSE protected header, missing `id` field");
350+
// };
351+
// decode_cbor_uuid(value)
352+
// .map_err(|e| anyhow::anyhow!("Invalid COSE protected header `id` field, err:
353+
// {e}"))?;
354+
355+
// let Some((_, value)) = cose
356+
// .protected
357+
// .header
358+
// .rest
359+
// .iter()
360+
// .find(|(key, _)| key == &coset::Label::Text("ver".to_string()))
361+
// else {
362+
// anyhow::bail!("Invalid COSE protected header, missing `ver` field");
363+
// };
364+
// decode_cbor_uuid(value)
365+
// .map_err(|e| anyhow::anyhow!("Invalid COSE protected header `ver` field, err:
366+
// {e}"))?;
367+
368+
// if let Some((_, value)) = cose
369+
// .protected
370+
// .header
371+
// .rest
372+
// .iter()
373+
// .find(|(key, _)| key == &coset::Label::Text("ref".to_string()))
374+
// {
375+
// decode_cbor_document_ref(value)
376+
// .map_err(|e| anyhow::anyhow!("Invalid COSE protected header `ref` field, err:
377+
// {e}"))?; }
378+
379+
// if let Some((_, value)) = cose
380+
// .protected
381+
// .header
382+
// .rest
383+
// .iter()
384+
// .find(|(key, _)| key == &coset::Label::Text("template".to_string()))
385+
// {
386+
// decode_cbor_document_ref(value).map_err(|e| {
387+
// anyhow::anyhow!("Invalid COSE protected header `template` field, err: {e}")
388+
// })?;
389+
// }
390+
391+
// if let Some((_, value)) = cose
392+
// .protected
393+
// .header
394+
// .rest
395+
// .iter()
396+
// .find(|(key, _)| key == &coset::Label::Text("reply".to_string()))
397+
// {
398+
// decode_cbor_document_ref(value).map_err(|e| {
399+
// anyhow::anyhow!("Invalid COSE protected header `reply` field, err: {e}")
400+
// })?;
401+
// }
402+
403+
// if let Some((_, value)) = cose
404+
// .protected
405+
// .header
406+
// .rest
407+
// .iter()
408+
// .find(|(key, _)| key == &coset::Label::Text("section".to_string()))
409+
// {
410+
// anyhow::ensure!(
411+
// value.is_text(),
412+
// "Invalid COSE protected header, missing `section` field"
413+
// );
414+
// }
422415

423416
Ok(())
424417
}

rust/signed_doc/src/metadata/additional_fields.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use anyhow::anyhow;
44
use coset::{cbor::Value, Label, ProtectedHeader};
55

6-
use super::{cose_protected_header_find, DocumentRef, UuidV4};
6+
use super::{cose_protected_header_find, decode_cbor_uuid, encode_cbor_value, DocumentRef, UuidV4};
77

88
/// Additional Metadata Fields.
99
///
@@ -33,25 +33,30 @@ pub struct AdditionalFields {
3333

3434
impl AdditionalFields {
3535
/// Returns the COSE Sign protected header REST fields.
36-
pub fn header_rest(&self) -> Vec<(Label, Value)> {
37-
self.into()
36+
///
37+
/// # Errors
38+
/// If any internal field cannot be converted into `Value`.
39+
pub fn header_rest(&self) -> anyhow::Result<Vec<(Label, Value)>> {
40+
self.try_into()
3841
}
3942
}
4043

41-
impl From<&AdditionalFields> for Vec<(Label, Value)> {
42-
fn from(fields: &AdditionalFields) -> Self {
44+
impl TryFrom<&AdditionalFields> for Vec<(Label, Value)> {
45+
type Error = anyhow::Error;
46+
47+
fn try_from(fields: &AdditionalFields) -> anyhow::Result<Self> {
4348
let mut vec = Vec::new();
4449

4550
if let Some(doc_ref) = &fields.doc_ref {
46-
vec.push((Label::Text("ref".to_string()), doc_ref.into()));
51+
vec.push((Label::Text("ref".to_string()), doc_ref.try_into()?));
4752
}
4853

4954
if let Some(template) = &fields.template {
50-
vec.push((Label::Text("template".to_string()), template.into()));
55+
vec.push((Label::Text("template".to_string()), template.try_into()?));
5156
}
5257

5358
if let Some(reply) = &fields.reply {
54-
vec.push((Label::Text("reply".to_string()), reply.into()));
59+
vec.push((Label::Text("reply".to_string()), reply.try_into()?));
5560
}
5661

5762
if let Some(section) = &fields.section {
@@ -71,31 +76,34 @@ impl From<&AdditionalFields> for Vec<(Label, Value)> {
7176
}
7277

7378
if let Some(brand_id) = &fields.brand_id {
74-
vec.push((Label::Text("brand_id".to_string()), Value::from(*brand_id)));
79+
vec.push((
80+
Label::Text("brand_id".to_string()),
81+
encode_cbor_value(brand_id)?,
82+
));
7583
}
7684

7785
if let Some(campaign_id) = &fields.campaign_id {
7886
vec.push((
7987
Label::Text("campaign_id".to_string()),
80-
Value::from(*campaign_id),
88+
encode_cbor_value(campaign_id)?,
8189
));
8290
}
8391

8492
if let Some(election_id) = &fields.election_id {
8593
vec.push((
8694
Label::Text("election_id".to_string()),
87-
Value::from(*election_id),
95+
encode_cbor_value(election_id)?,
8896
));
8997
}
9098

9199
if let Some(category_id) = &fields.category_id {
92100
vec.push((
93101
Label::Text("category_id".to_string()),
94-
Value::from(*category_id),
102+
encode_cbor_value(*category_id)?,
95103
));
96104
}
97105

98-
vec
106+
Ok(vec)
99107
}
100108
}
101109

@@ -201,7 +209,7 @@ impl TryFrom<&ProtectedHeader> for AdditionalFields {
201209
if let Some(cbor_doc_brand_id) =
202210
cose_protected_header_find(protected, |key| key == &Label::Text("brand_id".to_string()))
203211
{
204-
match UuidV4::try_from(cbor_doc_brand_id) {
212+
match decode_cbor_uuid(cbor_doc_brand_id.clone()) {
205213
Ok(brand_id) => {
206214
extra.brand_id = Some(brand_id);
207215
},
@@ -216,7 +224,7 @@ impl TryFrom<&ProtectedHeader> for AdditionalFields {
216224
if let Some(cbor_doc_campaign_id) = cose_protected_header_find(protected, |key| {
217225
key == &Label::Text("campaign_id".to_string())
218226
}) {
219-
match UuidV4::try_from(cbor_doc_campaign_id) {
227+
match decode_cbor_uuid(cbor_doc_campaign_id.clone()) {
220228
Ok(campaign_id) => {
221229
extra.campaign_id = Some(campaign_id);
222230
},
@@ -231,7 +239,7 @@ impl TryFrom<&ProtectedHeader> for AdditionalFields {
231239
if let Some(cbor_doc_election_id) = cose_protected_header_find(protected, |key| {
232240
key == &Label::Text("election_id".to_string())
233241
}) {
234-
match UuidV4::try_from(cbor_doc_election_id) {
242+
match decode_cbor_uuid(cbor_doc_election_id.clone()) {
235243
Ok(election_id) => {
236244
extra.election_id = Some(election_id);
237245
},
@@ -246,7 +254,7 @@ impl TryFrom<&ProtectedHeader> for AdditionalFields {
246254
if let Some(cbor_doc_category_id) = cose_protected_header_find(protected, |key| {
247255
key == &Label::Text("category_id".to_string())
248256
}) {
249-
match UuidV4::try_from(cbor_doc_category_id) {
257+
match decode_cbor_uuid(cbor_doc_category_id.clone()) {
250258
Ok(category_id) => {
251259
extra.category_id = Some(category_id);
252260
},

0 commit comments

Comments
 (0)