Skip to content

Commit 8c26d97

Browse files
authored
feat(rust/signed-doc): SignatureKidRule, ParametersRule and ReplyRule initialisation from spec (#550)
* added new Signers type * wip * add ReplyRule initialisation * wip * wip * fix * cleanup * fix clippy
1 parent 8c0be15 commit 8c26d97

File tree

15 files changed

+262
-77
lines changed

15 files changed

+262
-77
lines changed

rust/catalyst-signed-doc-macro/src/types_consts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ pub(crate) fn catalyst_signed_documents_types_consts_impl() -> anyhow::Result<To
99
let spec = CatalystSignedDocSpec::load_signed_doc_spec()?;
1010

1111
let mut consts_definitions = Vec::new();
12-
for (doc_name, doc_spec) in spec.docs {
12+
for (doc_name, doc_spec) in spec.docs.iter() {
1313
if doc_spec.draft {
1414
continue;
1515
}
1616
let const_type_name_ident = doc_name.ident();
1717
let doc_name = doc_name.name();
18-
let type_uuid = doc_spec.doc_type;
18+
let type_uuid = &doc_spec.doc_type;
1919

2020
let const_definition = quote! {
2121
#[doc = #doc_name ]

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,36 @@ pub mod headers;
88
pub mod is_required;
99
pub mod metadata;
1010
pub mod payload;
11+
pub mod signers;
1112

12-
use std::{collections::HashMap, fmt::Display};
13+
use std::{collections::HashMap, fmt::Display, ops::Deref};
1314

1415
use build_info as build_info_lib;
1516

16-
use crate::{copyright::Copyright, headers::Headers, metadata::Metadata, payload::Payload};
17+
use crate::{
18+
copyright::Copyright, headers::Headers, metadata::Metadata, payload::Payload, signers::Signers,
19+
};
1720

1821
build_info_lib::build_info!(pub(crate) fn build_info);
1922

2023
/// Catalyst Signed Document spec representation struct
2124
#[derive(serde::Deserialize)]
2225
pub struct CatalystSignedDocSpec {
23-
pub docs: HashMap<DocumentName, DocSpec>,
26+
pub docs: DocSpecs,
2427
copyright: Copyright,
2528
}
2629

30+
#[derive(serde::Deserialize)]
31+
pub struct DocSpecs(HashMap<DocumentName, DocSpec>);
32+
33+
impl Deref for DocSpecs {
34+
type Target = HashMap<DocumentName, DocSpec>;
35+
36+
fn deref(&self) -> &Self::Target {
37+
&self.0
38+
}
39+
}
40+
2741
// A thin wrapper over the string document name values
2842
#[derive(serde::Deserialize, PartialEq, Eq, Hash)]
2943
pub struct DocumentName(String);
@@ -66,6 +80,7 @@ pub struct DocSpec {
6680
pub doc_type: String,
6781
pub headers: Headers,
6882
pub metadata: Metadata,
83+
pub signers: Signers,
6984
pub payload: Payload,
7085
}
7186

rust/catalyst-signed-doc-spec/src/metadata/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! `metadata` field definition
22
33
pub mod doc_ref;
4+
pub mod parameters;
5+
pub mod reply;
46
pub mod template;
57

68
/// Document's metadata fields definition
@@ -10,4 +12,6 @@ pub struct Metadata {
1012
pub template: template::Template,
1113
#[serde(rename = "ref")]
1214
pub doc_ref: doc_ref::Ref,
15+
pub reply: reply::Reply,
16+
pub parameters: parameters::Parameters,
1317
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! `signed_doc.json` "parameters" field JSON definition
2+
3+
use std::ops::Deref;
4+
5+
use crate::metadata::doc_ref::Ref;
6+
7+
/// `signed_doc.json` "parameters" field JSON object
8+
#[derive(serde::Deserialize)]
9+
pub struct Parameters(pub Ref);
10+
11+
impl Deref for Parameters {
12+
type Target = Ref;
13+
14+
fn deref(&self) -> &Self::Target {
15+
&self.0
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! `signed_doc.json` "reply" field JSON definition
2+
3+
use std::ops::Deref;
4+
5+
use crate::metadata::doc_ref::Ref;
6+
7+
/// `signed_doc.json` "reply" field JSON object
8+
#[derive(serde::Deserialize)]
9+
pub struct Reply(pub Ref);
10+
11+
impl Deref for Reply {
12+
type Target = Ref;
13+
14+
fn deref(&self) -> &Self::Target {
15+
&self.0
16+
}
17+
}
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
//! `signed_doc.json` "template" field JSON definition
22
3-
use crate::{is_required::IsRequired, DocumentName};
3+
use std::ops::Deref;
4+
5+
use crate::metadata::doc_ref::Ref;
46

57
/// `signed_doc.json` "template" field JSON object
68
#[derive(serde::Deserialize)]
7-
#[allow(clippy::missing_docs_in_private_items, dead_code)]
8-
pub struct Template {
9-
pub required: IsRequired,
10-
#[serde(rename = "type")]
11-
pub doc_type: Option<DocumentName>,
12-
pub multiple: Option<bool>,
9+
pub struct Template(pub Ref);
10+
11+
impl Deref for Template {
12+
type Target = Ref;
13+
14+
fn deref(&self) -> &Self::Target {
15+
&self.0
16+
}
1317
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//! 'signers' field definition
2+
3+
pub mod roles;
4+
5+
/// Document's 'signers' fields definition
6+
#[derive(serde::Deserialize)]
7+
#[allow(clippy::missing_docs_in_private_items)]
8+
pub struct Signers {
9+
pub roles: roles::Roles,
10+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! 'roles' field definition
2+
3+
/// Document's 'roles' fields definition
4+
#[derive(serde::Deserialize)]
5+
#[allow(clippy::missing_docs_in_private_items)]
6+
pub struct Roles {
7+
pub user: Vec<Role>,
8+
}
9+
10+
/// Role definition
11+
#[derive(serde::Deserialize)]
12+
#[allow(clippy::missing_docs_in_private_items)]
13+
pub enum Role {
14+
/// Role 0 - A registered User / Voter - Base Role
15+
Registered,
16+
/// Registered for posting proposals
17+
Proposer,
18+
/// Registered as a rep for voting purposes.
19+
Representative,
20+
}

rust/signed_doc/src/validator/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ fn proposal_rule() -> Rules {
4949
allowed_type: PROPOSAL_FORM_TEMPLATE.clone(),
5050
},
5151
parameters: ParametersRule::Specified {
52-
exp_parameters_type: parameters.clone(),
52+
allowed_type: parameters.clone(),
5353
optional: false,
5454
},
5555
doc_ref: RefRule::NotSpecified,
5656
reply: ReplyRule::NotSpecified,
5757
section: SectionRule::NotSpecified,
5858
content: ContentRule::NotNil,
5959
kid: SignatureKidRule {
60-
exp: &[RoleId::Proposer],
60+
allowed_roles: vec![RoleId::Proposer],
6161
},
6262
signature: SignatureRule { mutlisig: false },
6363
original_author: OriginalAuthorRule,
@@ -88,22 +88,22 @@ fn proposal_comment_rule() -> Rules {
8888
allowed_type: PROPOSAL_COMMENT_FORM_TEMPLATE.clone(),
8989
},
9090
doc_ref: RefRule::Specified {
91-
exp_ref_types: vec![PROPOSAL.clone()],
91+
allowed_type: vec![PROPOSAL.clone()],
9292
multiple: false,
9393
optional: false,
9494
},
9595
reply: ReplyRule::Specified {
96-
exp_reply_type: PROPOSAL_COMMENT.clone(),
96+
allowed_type: PROPOSAL_COMMENT.clone(),
9797
optional: true,
9898
},
9999
section: SectionRule::NotSpecified,
100100
parameters: ParametersRule::Specified {
101-
exp_parameters_type: parameters.clone(),
101+
allowed_type: parameters.clone(),
102102
optional: false,
103103
},
104104
content: ContentRule::NotNil,
105105
kid: SignatureKidRule {
106-
exp: &[RoleId::Role0],
106+
allowed_roles: vec![RoleId::Role0],
107107
},
108108
signature: SignatureRule { mutlisig: false },
109109
original_author: OriginalAuthorRule,
@@ -143,19 +143,19 @@ fn proposal_submission_action_rule() -> Rules {
143143
},
144144
template: TemplateRule::NotSpecified,
145145
parameters: ParametersRule::Specified {
146-
exp_parameters_type: parameters,
146+
allowed_type: parameters,
147147
optional: false,
148148
},
149149
doc_ref: RefRule::Specified {
150-
exp_ref_types: vec![PROPOSAL.clone()],
150+
allowed_type: vec![PROPOSAL.clone()],
151151
multiple: false,
152152
optional: false,
153153
},
154154
reply: ReplyRule::NotSpecified,
155155
section: SectionRule::NotSpecified,
156156
content: ContentRule::StaticSchema(ContentSchema::Json(proposal_action_json_schema)),
157157
kid: SignatureKidRule {
158-
exp: &[RoleId::Proposer],
158+
allowed_roles: vec![RoleId::Proposer],
159159
},
160160
signature: SignatureRule { mutlisig: false },
161161
original_author: OriginalAuthorRule,

rust/signed_doc/src/validator/rules/doc_ref.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! `ref` rule type impl.
22
3-
use std::collections::HashMap;
4-
3+
use catalyst_signed_doc_spec::{is_required::IsRequired, metadata::doc_ref::Ref, DocSpecs};
54
use catalyst_types::problem_report::ProblemReport;
65

76
use crate::{
@@ -14,8 +13,8 @@ use crate::{
1413
pub(crate) enum RefRule {
1514
/// Is 'ref' specified
1615
Specified {
17-
/// expected `type` field of the referenced doc
18-
exp_ref_types: Vec<DocType>,
16+
/// allowed `type` field of the referenced doc
17+
allowed_type: Vec<DocType>,
1918
/// allows multiple document references or only one
2019
multiple: bool,
2120
/// optional flag for the `ref` field
@@ -27,20 +26,24 @@ pub(crate) enum RefRule {
2726
impl RefRule {
2827
/// Generating `RefRule` from specs
2928
pub(crate) fn new(
30-
docs: &HashMap<catalyst_signed_doc_spec::DocumentName, catalyst_signed_doc_spec::DocSpec>,
31-
ref_spec: &catalyst_signed_doc_spec::metadata::doc_ref::Ref,
29+
docs: &DocSpecs,
30+
spec: &Ref,
3231
) -> anyhow::Result<Self> {
33-
let optional = match ref_spec.required {
34-
catalyst_signed_doc_spec::is_required::IsRequired::Yes => false,
35-
catalyst_signed_doc_spec::is_required::IsRequired::Optional => true,
36-
catalyst_signed_doc_spec::is_required::IsRequired::Excluded => {
32+
let optional = match spec.required {
33+
IsRequired::Yes => false,
34+
IsRequired::Optional => true,
35+
IsRequired::Excluded => {
36+
anyhow::ensure!(
37+
spec.doc_type.is_empty() && spec.multiple.is_none(),
38+
"'type' and 'multiple' fields could not been specified when 'required' is 'excluded' for 'ref' metadata definition"
39+
);
3740
return Ok(Self::NotSpecified);
3841
},
3942
};
4043

41-
anyhow::ensure!(!ref_spec.doc_type.is_empty(), "'type' field should exists and has at least one entry for the required 'ref' metadata definition");
44+
anyhow::ensure!(!spec.doc_type.is_empty(), "'type' field should exists and has at least one entry for the required 'ref' metadata definition");
4245

43-
let exp_ref_types = ref_spec.doc_type.iter().try_fold(
46+
let exp_ref_types = spec.doc_type.iter().try_fold(
4447
Vec::new(),
4548
|mut res, doc_name| -> anyhow::Result<_> {
4649
let docs_spec = docs.get(doc_name).ok_or(anyhow::anyhow!(
@@ -51,12 +54,12 @@ impl RefRule {
5154
},
5255
)?;
5356

54-
let multiple = ref_spec.multiple.ok_or(anyhow::anyhow!(
57+
let multiple = spec.multiple.ok_or(anyhow::anyhow!(
5558
"'multiple' field should exists for the required 'ref' metadata definition"
5659
))?;
5760

5861
Ok(Self::Specified {
59-
exp_ref_types,
62+
allowed_type: exp_ref_types,
6063
multiple,
6164
optional,
6265
})
@@ -73,7 +76,7 @@ impl RefRule {
7376
{
7477
let context: &str = "Ref rule check";
7578
if let Self::Specified {
76-
exp_ref_types,
79+
allowed_type: exp_ref_types,
7780
multiple,
7881
optional,
7982
} = self
@@ -462,7 +465,7 @@ mod tests {
462465
let doc = doc_gen(&exp_types, &mut provider);
463466

464467
let non_optional_res = RefRule::Specified {
465-
exp_ref_types: exp_types.to_vec(),
468+
allowed_type: exp_types.to_vec(),
466469
multiple: true,
467470
optional: false,
468471
}
@@ -471,7 +474,7 @@ mod tests {
471474
.unwrap();
472475

473476
let optional_res = RefRule::Specified {
474-
exp_ref_types: exp_types.to_vec(),
477+
allowed_type: exp_types.to_vec(),
475478
multiple: true,
476479
optional: true,
477480
}
@@ -564,7 +567,7 @@ mod tests {
564567
let doc = doc_gen(&exp_types, &mut provider);
565568

566569
let non_optional_res = RefRule::Specified {
567-
exp_ref_types: exp_types.to_vec(),
570+
allowed_type: exp_types.to_vec(),
568571
multiple: false,
569572
optional: false,
570573
}
@@ -573,7 +576,7 @@ mod tests {
573576
.unwrap();
574577

575578
let optional_res = RefRule::Specified {
576-
exp_ref_types: exp_types.to_vec(),
579+
allowed_type: exp_types.to_vec(),
577580
multiple: false,
578581
optional: true,
579582
}
@@ -589,7 +592,7 @@ mod tests {
589592
async fn ref_specified_optional_test() {
590593
let provider = TestCatalystProvider::default();
591594
let rule = RefRule::Specified {
592-
exp_ref_types: vec![UuidV4::new().into()],
595+
allowed_type: vec![UuidV4::new().into()],
593596
multiple: true,
594597
optional: true,
595598
};
@@ -599,7 +602,7 @@ mod tests {
599602

600603
let provider = TestCatalystProvider::default();
601604
let rule = RefRule::Specified {
602-
exp_ref_types: vec![UuidV4::new().into()],
605+
allowed_type: vec![UuidV4::new().into()],
603606
multiple: true,
604607
optional: false,
605608
};

0 commit comments

Comments
 (0)