Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions rust/signed_doc/src/cid_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,6 @@
//! - **Hash function**: Only SHA2-256 is supported (32-byte digest)
//! - **Codec**: Fixed to CBOR (0x51)
//! - **Output size**: 36 bytes in binary format
//!
//! ## Example
//!
//! ```no_run
//! # use catalyst_signed_doc::{CatalystSignedDocument, cid_v1::Cid};
//! # let doc: CatalystSignedDocument = todo!();
//! let cid = doc.to_cid_v1()?;
//! let cid_string = cid.to_string();
//! // Result: "b..." (base32-encoded CID v1)
//! # Ok::<(), anyhow::Error>(())
//! ```

use std::{fmt, ops::Deref, str::FromStr};

Expand Down
36 changes: 23 additions & 13 deletions rust/signed_doc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,33 +254,43 @@ impl CatalystSignedDocument {
Ok(minicbor::decode_with(bytes, &mut policy)?)
}

/// Generate a CID v1 (Content Identifier version 1) for this signed document.
/// Returns a `DocumentRef` for the current document.
///
/// Creates an IPFS-compatible content identifier using:
/// Generating a CID v1 (Content Identifier version 1) creates an IPFS-compatible
/// content identifier using:
/// - CID version 1
/// - CBOR multicodec (0x51)
/// - SHA2-256 multihash
///
/// # Errors
/// - CBOR serialization failure
/// - Multihash construction failure
pub fn to_cid_v1(&self) -> Result<cid_v1::Cid, cid_v1::CidError> {
let cbor_bytes = self
.to_bytes()
.map_err(|e| cid_v1::CidError::Encoding(e.to_string()))?;
cid_v1::to_cid_v1(&cbor_bytes)
/// - Missing 'id' field.
/// - Missing 'ver' field.
pub fn doc_ref(&self) -> anyhow::Result<DocumentRef> {
let cid = self.to_cid_v1()?;
Ok(DocumentRef::new(
self.doc_id()?,
self.doc_ver()?,
DocLocator::from(cid),
))
}

/// Generate a CID v1 and return it as a multibase-encoded string.
/// Generate a CID v1 (Content Identifier version 1) for this signed document.
///
/// Uses base32 encoding (CID v1 default). The resulting string starts with 'b'.
/// Creates an IPFS-compatible content identifier using:
/// - CID version 1
/// - CBOR multicodec (0x51)
/// - SHA2-256 multihash
///
/// # Errors
/// - CBOR serialization failure
/// - CID generation failure
pub fn to_cid_v1_string(&self) -> Result<String, cid_v1::CidError> {
let cid = self.to_cid_v1()?;
Ok(cid.to_string())
/// - Multihash construction failure
fn to_cid_v1(&self) -> Result<cid_v1::Cid, cid_v1::CidError> {
let cbor_bytes = self
.to_bytes()
.map_err(|e| cid_v1::CidError::Encoding(e.to_string()))?;
cid_v1::to_cid_v1(&cbor_bytes)
}
}

Expand Down
34 changes: 7 additions & 27 deletions rust/signed_doc/src/metadata/document_refs/doc_locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,38 +140,18 @@ impl Encode<()> for DocLocator {
}

#[cfg(test)]
pub(crate) mod tests {
mod tests {

use minicbor::{Decoder, Encoder};

use super::*;
use crate::{Builder, ContentType, UuidV7};

pub(crate) fn create_dummy_doc_locator() -> DocLocator {
use crate::UuidV4;

let id = UuidV7::new();
let ver = UuidV7::new();
let doc = Builder::new()
.with_json_metadata(serde_json::json!({
"id": id.to_string(),
"ver": ver.to_string(),
"type": UuidV4::new().to_string(),
"content-type": ContentType::Json,
}))
.expect("Should create metadata")
.with_json_content(&serde_json::json!({"test": "content"}))
.expect("Should set content")
.build()
.expect("Should build document");

let cid = doc.to_cid_v1().expect("Should generate CID");
DocLocator::from(cid)
}
use crate::{
Builder, ContentType, UuidV7, metadata::document_refs::tests::create_dummy_doc_ref,
};

#[test]
fn test_doc_locator_encode_decode() {
let locator = create_dummy_doc_locator();
let locator = create_dummy_doc_ref().doc_locator().clone();
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
locator.encode(&mut encoder, &mut ()).unwrap();
Expand All @@ -182,7 +162,7 @@ pub(crate) mod tests {

#[test]
fn test_doc_locator_display() {
let locator = create_dummy_doc_locator();
let locator = create_dummy_doc_ref().doc_locator().clone();
let display_str = locator.to_string();
assert!(
display_str.starts_with('b'),
Expand All @@ -192,7 +172,7 @@ pub(crate) mod tests {

#[test]
fn test_doc_locator_from_str() {
let locator = create_dummy_doc_locator();
let locator = create_dummy_doc_ref().doc_locator().clone();
let display_str = locator.to_string();
let parsed = display_str
.parse::<DocLocator>()
Expand Down
14 changes: 0 additions & 14 deletions rust/signed_doc/src/metadata/document_refs/doc_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use cbork_utils::{array::Array, decode_context::DecodeCtx};
use minicbor::{Decode, Encode};

use super::doc_locator::DocLocator;
use crate::CatalystSignedDocument;

/// Number of item that should be in each document reference instance.
const DOC_REF_ARR_ITEM: u64 = 3;
Expand Down Expand Up @@ -58,19 +57,6 @@ impl DocumentRef {
}
}

impl TryFrom<&CatalystSignedDocument> for DocumentRef {
type Error = anyhow::Error;

fn try_from(value: &CatalystSignedDocument) -> Result<Self, Self::Error> {
let cid = value.to_cid_v1()?;
Ok(Self::new(
value.doc_id()?,
value.doc_ver()?,
DocLocator::from(cid),
))
}
}

impl Display for DocumentRef {
fn fmt(
&self,
Expand Down
62 changes: 39 additions & 23 deletions rust/signed_doc/src/metadata/document_refs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,33 @@ mod serde_impl {
}

#[cfg(test)]
mod tests {
pub(crate) mod tests {

use catalyst_types::uuid::{CborContext, UuidV7};
use catalyst_types::uuid::{CborContext, UuidV4, UuidV7};
use minicbor::{Decoder, Encoder};
use test_case::test_case;

use super::{doc_locator::tests::create_dummy_doc_locator, *};
use super::*;
use crate::{ContentType, builder::Builder};

pub(crate) fn create_dummy_doc_ref() -> DocumentRef {
let id = UuidV7::new();
let ver = UuidV7::new();
let doc = Builder::new()
.with_json_metadata(serde_json::json!({
"id": id.to_string(),
"ver": ver.to_string(),
"type": UuidV4::new().to_string(),
"content-type": ContentType::Json,
}))
.expect("Should create metadata")
.with_json_content(&serde_json::json!({"test": "content"}))
.expect("Should set content")
.build()
.expect("Should build document");

doc.doc_ref().expect("Should generate DocumentRef")
}

#[test_case(
CompatibilityPolicy::Accept,
Expand Down Expand Up @@ -248,16 +268,17 @@ mod tests {
#[test_case(
CompatibilityPolicy::Accept,
{
let doc_ref = create_dummy_doc_ref();
let mut e = Encoder::new(Vec::new());
e.array(1)
.unwrap()
.array(3)
.unwrap()
.encode_with(UuidV7::new(), &mut CborContext::Untagged)
.encode_with(*doc_ref.id(), &mut CborContext::Untagged)
.unwrap()
.encode_with(UuidV7::new(), &mut CborContext::Untagged)
.encode_with(*doc_ref.ver(), &mut CborContext::Untagged)
.unwrap()
.encode(create_dummy_doc_locator())
.encode(doc_ref.doc_locator().clone())
.unwrap();
e
} ;
Expand All @@ -275,15 +296,15 @@ mod tests {

#[test_case(
CompatibilityPolicy::Accept,
|uuid: UuidV7, doc_loc: DocLocator| {
|id, ver, doc_loc| {
let mut e = Encoder::new(Vec::new());
e.array(1)
.unwrap()
.array(3)
.unwrap()
.encode_with(uuid, &mut CborContext::Tagged)
.encode_with(id, &mut CborContext::Tagged)
.unwrap()
.encode_with(uuid, &mut CborContext::Tagged)
.encode_with(ver, &mut CborContext::Tagged)
.unwrap()
.encode(doc_loc)
.unwrap();
Expand All @@ -293,15 +314,15 @@ mod tests {
)]
#[test_case(
CompatibilityPolicy::Fail,
|uuid: UuidV7, doc_loc: DocLocator| {
|id, ver, doc_loc| {
let mut e = Encoder::new(Vec::new());
e.array(1)
.unwrap()
.array(3)
.unwrap()
.encode_with(uuid, &mut CborContext::Tagged)
.encode_with(id, &mut CborContext::Tagged)
.unwrap()
.encode_with(uuid, &mut CborContext::Tagged)
.encode_with(ver, &mut CborContext::Tagged)
.unwrap()
.encode(doc_loc)
.unwrap();
Expand All @@ -311,26 +332,21 @@ mod tests {
)]
fn test_valid_cbor_decode(
mut policy: CompatibilityPolicy,
e_gen: impl FnOnce(UuidV7, DocLocator) -> Encoder<Vec<u8>>,
e_gen: impl FnOnce(UuidV7, UuidV7, DocLocator) -> Encoder<Vec<u8>>,
) {
let uuid = UuidV7::new();
let doc_loc = create_dummy_doc_locator();
let e = e_gen(uuid, doc_loc.clone());
let doc_ref = create_dummy_doc_ref();
let e = e_gen(*doc_ref.id(), *doc_ref.ver(), doc_ref.doc_locator().clone());

let doc_refs =
DocumentRefs::decode(&mut Decoder::new(e.into_writer().as_slice()), &mut policy)
.unwrap();
assert_eq!(doc_refs.0, vec![DocumentRef::new(uuid, uuid, doc_loc)]);
assert_eq!(doc_refs.0, vec![doc_ref]);
}

#[test]
fn test_json_valid_serde() {
let uuid1 = UuidV7::new();
let uuid2 = UuidV7::new();
let doc_loc = create_dummy_doc_locator();

let doc_ref1 = DocumentRef::new(uuid1, uuid1, doc_loc.clone());
let doc_ref2 = DocumentRef::new(uuid2, uuid2, doc_loc);
let doc_ref1 = create_dummy_doc_ref();
let doc_ref2 = create_dummy_doc_ref();

let refs = DocumentRefs(vec![doc_ref1, doc_ref2]);

Expand Down
26 changes: 14 additions & 12 deletions rust/signed_doc/src/providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub mod tests {
CatalystId, CatalystIdProvider, CatalystSignedDocument, CatalystSignedDocumentProvider,
VerifyingKey,
};
use crate::{DocLocator, DocumentRef};
use crate::DocumentRef;

/// Simple testing implementation of `CatalystSignedDocumentProvider`,
#[derive(Default, Debug)]
Expand All @@ -74,28 +74,30 @@ pub mod tests {
}

impl TestCatalystProvider {
/// Inserts document into the `TestCatalystSignedDocumentProvider` where
/// if document reference is provided use that value.
/// if not use the id and version of the provided doc.
/// Inserts document into the `TestCatalystSignedDocumentProvider`.
///
/// # Errors
/// Returns error if document reference is not provided and its fail to create one
/// from the given doc.
pub fn add_document(
&mut self,
doc_ref: Option<DocumentRef>,
doc: &CatalystSignedDocument,
) -> anyhow::Result<()> {
if let Some(dr) = doc_ref {
self.signed_doc.insert(dr, doc.clone());
} else {
let cid = doc.to_cid_v1()?;
let dr = DocumentRef::new(doc.doc_id()?, doc.doc_ver()?, DocLocator::from(cid));
self.signed_doc.insert(dr, doc.clone());
}
let dr = doc.doc_ref()?;
self.signed_doc.insert(dr, doc.clone());
Ok(())
}

/// Inserts document into the `TestCatalystSignedDocumentProvider` using provided
/// `DocumentRef` as key.
pub fn add_document_with_ref(
&mut self,
doc_ref: DocumentRef,
doc: &CatalystSignedDocument,
) {
self.signed_doc.insert(doc_ref, doc.clone());
}

/// Inserts signing key into the `TestVerifyingKeyProvider`
pub fn add_sk(
&mut self,
Expand Down
Loading
Loading