Skip to content

Commit

Permalink
wip(rust/signed_doc): add basic structure for catalyst signed documen…
Browse files Browse the repository at this point in the history
…t API

* refactor code from mk_signed_doc example into src/lib.rs
  • Loading branch information
saibatizoku committed Dec 11, 2024
1 parent a7680af commit 3a6795d
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 23 deletions.
2 changes: 2 additions & 0 deletions .config/dictionaries/project.dic
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ upnp
ureq
userid
utimensat
uuidv4
uuidv7
UTXO
vitss
Vkey
Expand Down
6 changes: 3 additions & 3 deletions rust/signed_doc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ license.workspace = true
workspace = true

[dependencies]

[dev-dependencies]
clap = { version = "4.5.19", features = ["derive", "env"] }
anyhow = "1.0.89"
serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0"
Expand All @@ -22,3 +19,6 @@ coset = "0.3.7"
brotli = "7.0.0"
ed25519-dalek = { version = "2.1.1", features = ["pem"] }
uuid = { version = "1.10.0", features = ["v4", "v7", "serde"] }

[dev-dependencies]
clap = { version = "4.5.19", features = ["derive", "env"] }
21 changes: 1 addition & 20 deletions rust/signed_doc/examples/mk_signed_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use ed25519_dalek::{
ed25519::signature::Signer,
pkcs8::{DecodePrivateKey, DecodePublicKey},
};
use signed_doc::{DocumentRef, Metadata};

fn main() {
if let Err(err) = Cli::parse().exec() {
Expand Down Expand Up @@ -60,26 +61,6 @@ const CONTENT_ENCODING_KEY: &str = "content encoding";
const CONTENT_ENCODING_VALUE: &str = "br";
const UUID_CBOR_TAG: u64 = 37;

#[derive(Debug, serde::Deserialize)]
struct Metadata {
r#type: uuid::Uuid,
id: uuid::Uuid,
ver: uuid::Uuid,
r#ref: Option<DocumentRef>,
template: Option<DocumentRef>,
reply: Option<DocumentRef>,
section: Option<String>,
}

#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
enum DocumentRef {
/// Reference to the latest document
Latest { id: uuid::Uuid },
/// Reference to the specific document version
WithVer { id: uuid::Uuid, ver: uuid::Uuid },
}

fn encode_cbor_uuid(uuid: &uuid::Uuid) -> coset::cbor::Value {
coset::cbor::Value::Tag(
UUID_CBOR_TAG,
Expand Down
88 changes: 88 additions & 0 deletions rust/signed_doc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,89 @@
//! Catalyst documents signing crate
use std::{convert::TryFrom, sync::Arc};

/// Keep all the contents private.
/// Better even to use a structure like this. Wrapping in an Arc means we don't have to
/// manage the Arc anywhere else. These are likely to be large, best to have the Arc be
/// non-optional.
pub struct CatalystSignedDocument {
/// Catalyst Signed Document metadata, raw doc, with content errors.
inner: Arc<InnerCatalystSignedDocument>,
/// Content Errors found when parsing the Document
content_errors: Vec<String>,
}

/// Inner type that holds the Catalyst Signed Document with parsing errors.
struct InnerCatalystSignedDocument {
/// Document Metadata
_metadata: Metadata,
/// Raw payload
_raw_doc: Vec<u8>,
}

/// Document Metadata.
#[derive(Debug, serde::Deserialize)]
pub struct Metadata {
/// Document Type `UUIDv7`.
pub r#type: uuid::Uuid,
/// Document ID `UUIDv7`.
pub id: uuid::Uuid,
/// Document Version `UUIDv7`.
pub ver: uuid::Uuid,
/// Reference to the latest document.
pub r#ref: Option<DocumentRef>,
/// Reference to the document template.
pub template: Option<DocumentRef>,
/// Reference to the document reply.
pub reply: Option<DocumentRef>,
/// Reference to the document section.
pub section: Option<String>,
}

/// Reference to a Document.
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum DocumentRef {
/// Reference to the latest document
Latest {
/// Document ID UUID
id: uuid::Uuid,
},
/// Reference to the specific document version
WithVer {
/// Document ID UUID
id: uuid::Uuid,
/// Document Version UUID
ver: uuid::Uuid,
},
}

// Do this instead of `new` if we are converting a single parameter into a struct/type we
// should use either `From` or `TryFrom` and reserve `new` for cases where we need
// multiple parameters to actually create the type. This is much more elegant to use this
// way, in code.
impl TryFrom<Vec<u8>> for CatalystSignedDocument {
type Error = &'static str;

fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
todo!();
}
}

impl CatalystSignedDocument {
/// Invalid Doc Type UUID
const INVALID_UUID: uuid::Uuid = uuid::Uuid::from_bytes([0x00; 16]);

// A bunch of getters to access the contents, or reason through the document, such as.

/// Are there any validation errors (as opposed to structural errors.
#[must_use]
pub fn has_error(&self) -> bool {
!self.content_errors.is_empty()
}

/// Return Document Type UUID.
#[must_use]
pub fn doc_type(&self) -> uuid::Uuid {
INVALID_UUID
} // Can compare it against INVALID_DOC_TYPE to see if its valid or not.
}

0 comments on commit 3a6795d

Please sign in to comment.