Skip to content

Commit b703f01

Browse files
Mr-Leshiystevenj
andauthored
feat(rust/signed-doc): Proper CDDL schema processing (#626)
* add a new variant for schema, `Cddl` * wip * wip * wip * wip * wip * wip * fix * fix spelling * fix --------- Co-authored-by: Steven Johnson <stevenj@users.noreply.github.com>
1 parent 5cefff8 commit b703f01

File tree

13 files changed

+161
-169
lines changed

13 files changed

+161
-169
lines changed

rust/catalyst-signed-doc-spec/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ license.workspace = true
1111
workspace = true
1212

1313
[dependencies]
14+
catalyst-types = { version = "0.0.11", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.11" }
15+
cbork-cddl-parser = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cbork-cddl-parser/v0.0.3" }
16+
1417
serde_json = "1.0.142"
1518
anyhow = "1.0.99"
1619
serde = { version = "1.0.219", features = ["derive"] }
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//! 'cddlDefinitions' field definition
2+
3+
use std::{collections::HashMap, fmt::Display};
4+
5+
use cbork_cddl_parser::validate_cddl;
6+
7+
#[derive(serde::Deserialize)]
8+
pub struct CddlDefinitions(HashMap<CddlType, CddlDef>);
9+
10+
#[derive(Clone, serde::Deserialize, PartialEq, Eq, Hash)]
11+
pub struct CddlType(String);
12+
13+
#[derive(serde::Deserialize)]
14+
struct CddlDef {
15+
def: String,
16+
requires: Vec<CddlType>,
17+
}
18+
19+
impl Display for CddlType {
20+
fn fmt(
21+
&self,
22+
f: &mut std::fmt::Formatter<'_>,
23+
) -> std::fmt::Result {
24+
self.0.fmt(f)
25+
}
26+
}
27+
28+
impl CddlDef {
29+
fn get_cddl_spec(
30+
&self,
31+
cddl_type: &CddlType,
32+
) -> String {
33+
format!("{cddl_type}={}\n", self.def)
34+
}
35+
}
36+
37+
impl CddlDefinitions {
38+
fn find_cddl_def(
39+
&self,
40+
cddl_type: &CddlType,
41+
) -> anyhow::Result<&CddlDef> {
42+
self.0.get(cddl_type).ok_or(anyhow::anyhow!(
43+
"Cannot find a cddl definition for the {cddl_type}"
44+
))
45+
}
46+
47+
/// Returns a full CDDL specification schema.
48+
/// Performs
49+
///
50+
/// # Errors
51+
/// - Cannot find a cddl definition
52+
/// - Not a valid resulted CDDL spec
53+
pub fn get_cddl_spec(
54+
&self,
55+
cddl_type: &CddlType,
56+
) -> anyhow::Result<String> {
57+
let def = self.find_cddl_def(cddl_type)?;
58+
59+
let spec = def.get_cddl_spec(cddl_type);
60+
let mut requires = def.requires.clone();
61+
62+
let mut imports = HashMap::new();
63+
while let Some(req) = requires.pop() {
64+
let req_def = self.find_cddl_def(&req)?;
65+
let req_spec = req_def.get_cddl_spec(&req);
66+
if imports.insert(req, req_spec).is_none() {
67+
requires.extend(req_def.requires.clone());
68+
}
69+
}
70+
71+
let mut spec = imports.values().fold(spec, |mut spec, import_spec| {
72+
spec.push_str(import_spec);
73+
spec
74+
});
75+
76+
validate_cddl(&mut spec, &cbork_cddl_parser::Extension::CDDL)?;
77+
Ok(spec)
78+
}
79+
}

rust/catalyst-signed-doc-spec/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
#![allow(missing_docs, clippy::missing_docs_in_private_items)]
44

5-
pub mod copyright;
5+
pub mod cddl_definitions;
6+
mod copyright;
67
pub mod doc_types;
78
pub mod headers;
89
pub mod is_required;
@@ -15,16 +16,19 @@ use std::{collections::HashMap, fmt::Display, ops::Deref};
1516
use build_info as build_info_lib;
1617

1718
use crate::{
18-
copyright::Copyright, headers::Headers, metadata::Metadata, payload::Payload, signers::Signers,
19+
cddl_definitions::CddlDefinitions, copyright::Copyright, headers::Headers, metadata::Metadata,
20+
payload::Payload, signers::Signers,
1921
};
2022

2123
build_info_lib::build_info!(pub(crate) fn build_info);
2224

2325
/// Catalyst Signed Document spec representation struct
2426
#[derive(serde::Deserialize)]
2527
pub struct CatalystSignedDocSpec {
26-
pub docs: DocSpecs,
28+
#[serde(rename = "cddlDefinitions")]
29+
pub cddl_definitions: CddlDefinitions,
2730
copyright: Copyright,
31+
pub docs: DocSpecs,
2832
}
2933

3034
#[derive(serde::Deserialize)]
Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,40 @@
11
//! `signed_doc.json` "payload" field JSON definition
22
3+
use catalyst_types::json_schema::JsonSchema;
4+
use serde::Deserialize;
5+
6+
use crate::cddl_definitions::CddlType;
7+
38
/// `signed_doc.json` "payload" field JSON object
49
#[derive(serde::Deserialize)]
510
#[allow(clippy::missing_docs_in_private_items)]
611
pub struct Payload {
712
pub nil: bool,
8-
pub schema: Option<serde_json::Value>,
13+
pub schema: Option<Schema>,
14+
}
15+
16+
pub enum Schema {
17+
Cddl(CddlType),
18+
Json(JsonSchema),
19+
}
20+
21+
impl<'de> Deserialize<'de> for Schema {
22+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
23+
where D: serde::Deserializer<'de> {
24+
#[derive(serde::Deserialize)]
25+
#[serde(untagged)]
26+
pub enum SchemaSerde {
27+
Cddl(CddlType),
28+
Json(serde_json::Value),
29+
}
30+
31+
match SchemaSerde::deserialize(deserializer)? {
32+
SchemaSerde::Json(json) => {
33+
JsonSchema::try_from(&json)
34+
.map(Self::Json)
35+
.map_err(serde::de::Error::custom)
36+
},
37+
SchemaSerde::Cddl(cddl_type) => Ok(Self::Cddl(cddl_type)),
38+
}
39+
}
940
}

rust/signed_doc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ license.workspace = true
1111
workspace = true
1212

1313
[dependencies]
14-
catalyst-types = { version = "0.0.10", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.10" }
14+
catalyst-types = { version = "0.0.11", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.11" }
1515
cbork-utils = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cbork-utils-v0.0.2" }
1616

1717
catalyst-signed-doc-macro = { version = "0.0.1", path = "../catalyst-signed-doc-macro" }

rust/signed_doc/src/validator/json_schema.rs

Lines changed: 0 additions & 139 deletions
This file was deleted.

rust/signed_doc/src/validator/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Catalyst Signed Documents validation logic
22
3-
pub(crate) mod json_schema;
43
pub(crate) mod rules;
54

65
use std::{collections::HashMap, sync::LazyLock};

0 commit comments

Comments
 (0)