From 5995922fcf8277a02cabae7c9211ea4aee8cc22c Mon Sep 17 00:00:00 2001 From: Miroslav Kovar Date: Wed, 16 Aug 2023 11:47:02 +0200 Subject: [PATCH 1/2] Extract subset of changes made in didx PR Signed-off-by: Miroslav Kovar --- Cargo.lock | 14 +++ did_doc/src/schema/did_doc.rs | 23 ++++ did_doc/src/schema/types/url.rs | 1 + .../schema/verification_method/public_key.rs | 7 ++ did_doc_sov/src/error.rs | 2 + did_doc_sov/src/lib.rs | 109 +++++++++++++++++- did_doc_sov/src/service/aip1.rs | 12 ++ did_doc_sov/src/service/didcommv1.rs | 12 ++ did_doc_sov/src/service/didcommv2.rs | 12 ++ did_doc_sov/src/service/mod.rs | 19 ++- did_doc_sov/tests/builder.rs | 8 +- .../src/numalgos/numalgo2/generate/helpers.rs | 31 +++-- did_peer/src/peer_did/peer_did/mod.rs | 6 + public_key/src/error.rs | 2 + public_key/src/key.rs | 14 ++- public_key/src/key_type.rs | 4 +- 16 files changed, 256 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f09ea55f3f..7d1e2a5015 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,6 +427,13 @@ dependencies = [ "bs58 0.4.0", "chrono", "derive_builder 0.10.2", + "did_doc", + "did_doc_sov", + "did_key", + "did_parser", + "did_peer", + "did_resolver", + "did_resolver_registry", "diddoc_legacy", "env_logger 0.9.3", "futures", @@ -434,6 +441,7 @@ dependencies = [ "log", "messages", "openssl", + "public_key", "rand 0.7.3", "regex", "serde", @@ -458,7 +466,12 @@ dependencies = [ "aries_vcx_core", "async-trait", "derive_builder 0.11.2", + "did_key", + "did_peer", + "did_resolver_registry", + "did_resolver_sov", "log", + "public_key", "serde", "serde_json", "thiserror", @@ -3153,6 +3166,7 @@ version = "0.57.1" dependencies = [ "chrono", "derive_more", + "did_doc_sov", "diddoc_legacy", "isolang", "lazy_static", diff --git a/did_doc/src/schema/did_doc.rs b/did_doc/src/schema/did_doc.rs index 3dfa8c6399..bc54c55f9e 100644 --- a/did_doc/src/schema/did_doc.rs +++ b/did_doc/src/schema/did_doc.rs @@ -252,6 +252,29 @@ impl DidDocumentBuilder { } } +impl From> for DidDocumentBuilder { + fn from(did_document: DidDocument) -> Self { + let controller = match did_document.controller { + Some(OneOrList::List(list)) => list, + _ => Vec::new(), + }; + + Self { + id: did_document.id, + also_known_as: did_document.also_known_as, + controller, + verification_method: did_document.verification_method, + authentication: did_document.authentication, + assertion_method: did_document.assertion_method, + key_agreement: did_document.key_agreement, + capability_invocation: did_document.capability_invocation, + capability_delegation: did_document.capability_delegation, + service: did_document.service, + extra: did_document.extra, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/did_doc/src/schema/types/url.rs b/did_doc/src/schema/types/url.rs index b35d738a75..f6578fec59 100644 --- a/did_doc/src/schema/types/url.rs +++ b/did_doc/src/schema/types/url.rs @@ -5,6 +5,7 @@ use url::Url as UrlDep; use crate::error::DidDocumentBuilderError; +// TODO: This was bad idea, get rid of it #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct Url(UrlDep); diff --git a/did_doc/src/schema/verification_method/public_key.rs b/did_doc/src/schema/verification_method/public_key.rs index a1ad89829e..c392501d44 100644 --- a/did_doc/src/schema/verification_method/public_key.rs +++ b/did_doc/src/schema/verification_method/public_key.rs @@ -53,6 +53,13 @@ impl PublicKeyField { ), } } + + // TODO: Other formats + pub fn base58(&self) -> Result { + Ok(bs58::encode(self.key_decoded()?).into_string()) + } + + // TODO: This should expose a PublicKey getter } #[cfg(test)] diff --git a/did_doc_sov/src/error.rs b/did_doc_sov/src/error.rs index 42a1fa6ef3..022dae7032 100644 --- a/did_doc_sov/src/error.rs +++ b/did_doc_sov/src/error.rs @@ -10,4 +10,6 @@ pub enum DidDocumentSovError { UnexpectedServiceType(String), #[error("Index out of bounds: {0}")] IndexOutOfBounds(usize), + #[error("JSON error")] + JsonError(#[from] serde_json::Error), } diff --git a/did_doc_sov/src/lib.rs b/did_doc_sov/src/lib.rs index 454a3bb8ad..b5c1960c06 100644 --- a/did_doc_sov/src/lib.rs +++ b/did_doc_sov/src/lib.rs @@ -2,11 +2,15 @@ pub mod error; pub mod extra_fields; pub mod service; +use std::collections::HashMap; + use did_doc::{ did_parser::{Did, DidUrl}, schema::{ did_doc::{ControllerAlias, DidDocument, DidDocumentBuilder}, + service::Service, types::uri::Uri, + utils::OneOrList, verification_method::{VerificationMethod, VerificationMethodKind}, }, }; @@ -15,15 +19,15 @@ use serde::{de, Deserialize, Deserializer, Serialize}; use serde_json::Value; use service::ServiceSov; -#[derive(Serialize, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct DidDocumentSov { did_doc: DidDocument, services: Vec, } impl DidDocumentSov { - pub fn builder() -> DidDocumentSovBuilder { - DidDocumentSovBuilder::default() + pub fn builder(id: Did) -> DidDocumentSovBuilder { + DidDocumentSovBuilder::new(id) } pub fn id(&self) -> &Did { @@ -75,7 +79,6 @@ impl DidDocumentSov { } } -#[derive(Default)] pub struct DidDocumentSovBuilder { ddo_builder: DidDocumentBuilder, services: Vec, @@ -99,8 +102,20 @@ impl DidDocumentSovBuilder { self } + pub fn add_key_agreement(mut self, key_agreement: VerificationMethodKind) -> Self { + match key_agreement { + VerificationMethodKind::Resolved(ka) => { + self.ddo_builder = self.ddo_builder.add_key_agreement(ka); + } + VerificationMethodKind::Resolvable(ka_ref) => { + self.ddo_builder = self.ddo_builder.add_key_agreement_reference(ka_ref); + } + } + self + } + pub fn add_service(mut self, service: ServiceSov) -> Self { - self.services.push(service); + self.services.push(service.clone()); self } @@ -139,3 +154,87 @@ impl<'de> Deserialize<'de> for DidDocumentSov { }) } } + +impl Serialize for DidDocumentSov { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut builder: DidDocumentBuilder = self.did_doc.clone().into(); + + for service_sov in &self.services { + let service: Service = service_sov.clone().try_into().map_err(serde::ser::Error::custom)?; + builder = builder.add_service(service); + } + + builder.build().serialize(serializer) + } +} + +impl From for DidDocument { + fn from(ddo: DidDocumentSov) -> Self { + let mut ddo_builder = DidDocument::::builder(ddo.did_doc.id().clone()); + for service in ddo.service() { + ddo_builder = ddo_builder.add_service(service.clone().try_into().unwrap()); + } + if let Some(controller) = ddo.did_doc.controller() { + match controller { + OneOrList::One(controller) => { + ddo_builder = ddo_builder.add_controller(controller.clone()); + } + OneOrList::List(list) => { + for controller in list { + ddo_builder = ddo_builder.add_controller(controller.clone()); + } + } + } + } + for vm in ddo.verification_method() { + ddo_builder = ddo_builder.add_verification_method(vm.clone()); + } + for ka in ddo.key_agreement() { + match ka { + VerificationMethodKind::Resolved(ka) => { + ddo_builder = ddo_builder.add_key_agreement(ka.clone()); + } + VerificationMethodKind::Resolvable(ka_ref) => { + ddo_builder = ddo_builder.add_key_agreement_reference(ka_ref.clone()); + } + } + } + ddo_builder.build() + } +} + +impl From> for DidDocumentSov { + fn from(ddo: DidDocument) -> Self { + let mut builder = DidDocumentSov::builder(ddo.id().clone()); + for service in ddo.service() { + builder = builder.add_service(service.clone().try_into().unwrap()); + } + for vm in ddo.verification_method() { + builder = builder.add_verification_method(vm.clone()); + } + for ka in ddo.key_agreement() { + builder = builder.add_key_agreement(ka.clone()); + } + // TODO: Controller + builder.build() + } +} + +impl From>> for DidDocumentSov { + fn from(ddo: DidDocument>) -> Self { + let mut builder = DidDocumentSov::builder(ddo.id().clone()); + for service in ddo.service() { + builder = builder.add_service(service.clone().try_into().unwrap()); + } + for vm in ddo.verification_method() { + builder = builder.add_verification_method(vm.clone()); + } + for ka in ddo.key_agreement() { + builder = builder.add_key_agreement(ka.clone()); + } + builder.build() + } +} diff --git a/did_doc_sov/src/service/aip1.rs b/did_doc_sov/src/service/aip1.rs index 43dcfd858f..4ecbe36768 100644 --- a/did_doc_sov/src/service/aip1.rs +++ b/did_doc_sov/src/service/aip1.rs @@ -1,9 +1,12 @@ +use std::collections::HashMap; + use did_doc::schema::{ service::Service, types::{uri::Uri, url::Url}, utils::OneOrList, }; use serde::{Deserialize, Serialize}; +use serde_json::Value; use crate::{ error::DidDocumentSovError, @@ -59,6 +62,15 @@ impl TryFrom> for ServiceAIP1 { } } +impl TryFrom>> for ServiceAIP1 { + type Error = DidDocumentSovError; + + fn try_from(service: Service>) -> Result { + let extra = serde_json::from_value::(serde_json::to_value(service.extra())?)?; + Self::new(service.id().clone(), service.service_endpoint().clone(), extra) + } +} + impl<'de> Deserialize<'de> for ServiceAIP1 { fn deserialize(deserializer: D) -> Result where diff --git a/did_doc_sov/src/service/didcommv1.rs b/did_doc_sov/src/service/didcommv1.rs index bae374c3da..a779157bc2 100644 --- a/did_doc_sov/src/service/didcommv1.rs +++ b/did_doc_sov/src/service/didcommv1.rs @@ -1,9 +1,12 @@ +use std::collections::HashMap; + use did_doc::schema::{ service::Service, types::{uri::Uri, url::Url}, utils::OneOrList, }; use serde::{Deserialize, Serialize}; +use serde_json::Value; use crate::{ error::DidDocumentSovError, @@ -59,6 +62,15 @@ impl TryFrom> for ServiceDidCommV1 { } } +impl TryFrom>> for ServiceDidCommV1 { + type Error = DidDocumentSovError; + + fn try_from(service: Service>) -> Result { + let extra = serde_json::from_value::(serde_json::to_value(service.extra())?)?; + Self::new(service.id().clone(), service.service_endpoint().clone(), extra) + } +} + impl<'de> Deserialize<'de> for ServiceDidCommV1 { fn deserialize(deserializer: D) -> Result where diff --git a/did_doc_sov/src/service/didcommv2.rs b/did_doc_sov/src/service/didcommv2.rs index 583d3297a0..d956af7c95 100644 --- a/did_doc_sov/src/service/didcommv2.rs +++ b/did_doc_sov/src/service/didcommv2.rs @@ -1,9 +1,12 @@ +use std::collections::HashMap; + use did_doc::schema::{ service::Service, types::{uri::Uri, url::Url}, utils::OneOrList, }; use serde::{Deserialize, Serialize}; +use serde_json::Value; use crate::{ error::DidDocumentSovError, @@ -59,6 +62,15 @@ impl TryFrom> for ServiceDidCommV2 { } } +impl TryFrom>> for ServiceDidCommV2 { + type Error = DidDocumentSovError; + + fn try_from(service: Service>) -> Result { + let extra = serde_json::from_value::(serde_json::to_value(service.extra())?)?; + Self::new(service.id().clone(), service.service_endpoint().clone(), extra) + } +} + impl<'de> Deserialize<'de> for ServiceDidCommV2 { fn deserialize(deserializer: D) -> Result where diff --git a/did_doc_sov/src/service/mod.rs b/did_doc_sov/src/service/mod.rs index 1155174ed6..a78f76e477 100644 --- a/did_doc_sov/src/service/mod.rs +++ b/did_doc_sov/src/service/mod.rs @@ -1,10 +1,11 @@ -use std::fmt::Display; +use std::{collections::HashMap, fmt::Display}; use did_doc::schema::{ service::Service, types::{uri::Uri, url::Url}, }; use serde::{Deserialize, Serialize}; +use serde_json::Value; use crate::{error::DidDocumentSovError, extra_fields::ExtraFieldsSov}; @@ -83,6 +84,22 @@ impl TryFrom> for ServiceSov { } } +impl TryFrom>> for ServiceSov { + type Error = DidDocumentSovError; + + fn try_from(service: Service>) -> Result { + match service.extra().get("type") { + Some(service_type) => match service_type.as_str() { + Some("AIP1") => Ok(ServiceSov::AIP1(service.try_into()?)), + Some("DIDCommV1") => Ok(ServiceSov::DIDCommV1(service.try_into()?)), + Some("DIDCommV2") => Ok(ServiceSov::DIDCommV2(service.try_into()?)), + _ => Err(DidDocumentSovError::UnexpectedServiceType(service_type.to_string())), + }, + None => Ok(ServiceSov::AIP1(service.try_into()?)), + } + } +} + impl TryFrom for Service { type Error = DidDocumentSovError; diff --git a/did_doc_sov/tests/builder.rs b/did_doc_sov/tests/builder.rs index 6e1e32828e..77fb7da4ce 100644 --- a/did_doc_sov/tests/builder.rs +++ b/did_doc_sov/tests/builder.rs @@ -16,7 +16,9 @@ fn test_service_build_aip1() { ExtraFieldsAIP1::default(), ) .unwrap(); - let did_doc = DidDocumentSov::builder().add_service(ServiceSov::AIP1(service)).build(); + let did_doc = DidDocumentSov::builder(Default::default()) + .add_service(ServiceSov::AIP1(service)) + .build(); let services = did_doc.service(); assert_eq!(services.len(), 1); let first_service = services.get(0).unwrap(); @@ -44,7 +46,7 @@ fn test_service_build_didcommv1() { extra_fields_didcommv1, ) .unwrap(); - let did_doc = DidDocumentSov::builder() + let did_doc = DidDocumentSov::builder(Default::default()) .add_service(ServiceSov::DIDCommV1(service)) .build(); let services = did_doc.service(); @@ -75,7 +77,7 @@ fn test_service_build_didcommv2() { extra_fields_didcommv2, ) .unwrap(); - let did_doc = DidDocumentSov::builder() + let did_doc = DidDocumentSov::builder(Default::default()) .add_service(ServiceSov::DIDCommV2(service)) .build(); let services = did_doc.service(); diff --git a/did_peer/src/numalgos/numalgo2/generate/helpers.rs b/did_peer/src/numalgos/numalgo2/generate/helpers.rs index 33c648bffc..34f03cd91c 100644 --- a/did_peer/src/numalgos/numalgo2/generate/helpers.rs +++ b/did_peer/src/numalgos/numalgo2/generate/helpers.rs @@ -1,8 +1,12 @@ use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine}; use did_doc::schema::{ - did_doc::DidDocument, service::Service, utils::OneOrList, verification_method::VerificationMethodKind, + did_doc::DidDocument, + service::Service, + utils::OneOrList, + verification_method::{VerificationMethod, VerificationMethodKind}, }; use did_doc_sov::extra_fields::ExtraFieldsSov; +use public_key::Key; use crate::{ error::DidPeerError, @@ -77,23 +81,32 @@ pub fn append_encoded_service_segment( } fn append_encoded_key_segment( - mut did: String, + did: String, did_document: &DidDocument, vm: &VerificationMethodKind, purpose: ElementPurpose, ) -> Result { - let vm = match vm { - VerificationMethodKind::Resolved(vm) => vm, + let vm = resolve_verification_method(did_document, vm)?; + let key = get_key_by_verification_method(vm)?; + Ok(append_key_to_did(did, key, purpose)) +} + +fn resolve_verification_method<'a>( + did_document: &'a DidDocument, + vm: &'a VerificationMethodKind, +) -> Result<&'a VerificationMethod, DidPeerError> { + match vm { + VerificationMethodKind::Resolved(vm) => Ok(vm), VerificationMethodKind::Resolvable(did_url) => did_document .dereference_key(did_url) - .ok_or(DidPeerError::InvalidKeyReference(did_url.to_string()))?, - }; + .ok_or(DidPeerError::InvalidKeyReference(did_url.to_string())), + } +} - let key = get_key_by_verification_method(vm)?; +fn append_key_to_did(mut did: String, key: Key, purpose: ElementPurpose) -> String { let encoded = format!(".{}{}", purpose, key.fingerprint()); did.push_str(&encoded); - - Ok(did) + did } fn abbreviate_service(service: &Service) -> Result { diff --git a/did_peer/src/peer_did/peer_did/mod.rs b/did_peer/src/peer_did/peer_did/mod.rs index b6f6467a5f..a2a675fe49 100644 --- a/did_peer/src/peer_did/peer_did/mod.rs +++ b/did_peer/src/peer_did/peer_did/mod.rs @@ -89,6 +89,12 @@ impl Display for PeerDid { } } +impl From> for Did { + fn from(peer_did: PeerDid) -> Self { + peer_did.did + } +} + #[cfg(test)] mod tests { use crate::peer_did::numalgos::numalgo2::Numalgo2; diff --git a/public_key/src/error.rs b/public_key/src/error.rs index a422ebe7a6..07cfbaeb63 100644 --- a/public_key/src/error.rs +++ b/public_key/src/error.rs @@ -4,6 +4,8 @@ use thiserror::Error; pub enum PublicKeyError { #[error("Base 64 decoding error")] Base64DecodingError(#[from] base64::DecodeError), + #[error("Base 58 decoding error")] + Base58DecodingError(#[from] bs58::decode::Error), #[error("Multibase decoding error")] MultibaseDecodingError(#[from] multibase::Error), #[error("Varint decoding error")] diff --git a/public_key/src/key.rs b/public_key/src/key.rs index 7e768f64bf..4abdd20834 100644 --- a/public_key/src/key.rs +++ b/public_key/src/key.rs @@ -1,8 +1,10 @@ +use serde::{Deserialize, Serialize}; + use crate::error::PublicKeyError; use super::KeyType; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Key { key_type: KeyType, key: Vec, @@ -45,6 +47,8 @@ impl Key { bs58::encode(&self.key).into_string() } + // TODO: base64, ... + pub fn multibase58(&self) -> String { multibase::encode(multibase::Base::Base58Btc, &self.key) } @@ -58,6 +62,14 @@ impl Key { }) } + pub fn from_base58(base58: &str, key_type: KeyType) -> Result { + let decoded_bytes = bs58::decode(base58).into_vec()?; + Ok(Self { + key_type, + key: decoded_bytes, + }) + } + fn strip_multicodec_prefix_if_present(key: Vec, key_type: &KeyType) -> Vec { if let Ok((value, remaining)) = unsigned_varint::decode::u64(&key) { if value == Into::::into(key_type) { diff --git a/public_key/src/key_type.rs b/public_key/src/key_type.rs index ab2f821e18..1c742018f4 100644 --- a/public_key/src/key_type.rs +++ b/public_key/src/key_type.rs @@ -1,6 +1,8 @@ +use serde::{Deserialize, Serialize}; + use crate::error::PublicKeyError; -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub enum KeyType { Ed25519, Bls12381g1g2, From ef7de69ee3cc86117af06a692753165c82ca0a4c Mon Sep 17 00:00:00 2001 From: Miroslav Kovar Date: Wed, 16 Aug 2023 16:43:37 +0200 Subject: [PATCH 2/2] Address code review Signed-off-by: Miroslav Kovar --- Cargo.lock | 14 -------------- did_doc_sov/src/extra_fields/aip1.rs | 1 + did_doc_sov/src/extra_fields/didcommv1.rs | 1 + did_doc_sov/src/extra_fields/didcommv2.rs | 1 + did_doc_sov/src/lib.rs | 7 ++++++- did_doc_sov/tests/serde.rs | 10 +++++++++- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d1e2a5015..f09ea55f3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,13 +427,6 @@ dependencies = [ "bs58 0.4.0", "chrono", "derive_builder 0.10.2", - "did_doc", - "did_doc_sov", - "did_key", - "did_parser", - "did_peer", - "did_resolver", - "did_resolver_registry", "diddoc_legacy", "env_logger 0.9.3", "futures", @@ -441,7 +434,6 @@ dependencies = [ "log", "messages", "openssl", - "public_key", "rand 0.7.3", "regex", "serde", @@ -466,12 +458,7 @@ dependencies = [ "aries_vcx_core", "async-trait", "derive_builder 0.11.2", - "did_key", - "did_peer", - "did_resolver_registry", - "did_resolver_sov", "log", - "public_key", "serde", "serde_json", "thiserror", @@ -3166,7 +3153,6 @@ version = "0.57.1" dependencies = [ "chrono", "derive_more", - "did_doc_sov", "diddoc_legacy", "isolang", "lazy_static", diff --git a/did_doc_sov/src/extra_fields/aip1.rs b/did_doc_sov/src/extra_fields/aip1.rs index e8f9155724..0ec8e4f44c 100644 --- a/did_doc_sov/src/extra_fields/aip1.rs +++ b/did_doc_sov/src/extra_fields/aip1.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)] +#[serde(deny_unknown_fields)] pub struct ExtraFieldsAIP1 {} diff --git a/did_doc_sov/src/extra_fields/didcommv1.rs b/did_doc_sov/src/extra_fields/didcommv1.rs index a9c95559b3..393cbb1821 100644 --- a/did_doc_sov/src/extra_fields/didcommv1.rs +++ b/did_doc_sov/src/extra_fields/didcommv1.rs @@ -4,6 +4,7 @@ use super::{AcceptType, KeyKind}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)] #[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct ExtraFieldsDidCommV1 { priority: u32, recipient_keys: Vec, diff --git a/did_doc_sov/src/extra_fields/didcommv2.rs b/did_doc_sov/src/extra_fields/didcommv2.rs index a48cf855fb..e66390dfb2 100644 --- a/did_doc_sov/src/extra_fields/didcommv2.rs +++ b/did_doc_sov/src/extra_fields/didcommv2.rs @@ -4,6 +4,7 @@ use super::{AcceptType, KeyKind}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)] #[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct ExtraFieldsDidCommV2 { routing_keys: Vec, #[serde(default)] diff --git a/did_doc_sov/src/lib.rs b/did_doc_sov/src/lib.rs index b5c1960c06..445d59e5cf 100644 --- a/did_doc_sov/src/lib.rs +++ b/did_doc_sov/src/lib.rs @@ -164,7 +164,12 @@ impl Serialize for DidDocumentSov { for service_sov in &self.services { let service: Service = service_sov.clone().try_into().map_err(serde::ser::Error::custom)?; - builder = builder.add_service(service); + // Not very efficient, but + // * we don't expect many services + // * does not require allowing to remove services from existing DDO or builder + if !self.did_doc.service().iter().any(|s| s.id() == service.id()) { + builder = builder.add_service(service); + } } builder.build().serialize(serializer) diff --git a/did_doc_sov/tests/serde.rs b/did_doc_sov/tests/serde.rs index 17fe1cb454..a2d43d251f 100644 --- a/did_doc_sov/tests/serde.rs +++ b/did_doc_sov/tests/serde.rs @@ -68,7 +68,7 @@ const DID_DOC_DATA: &'static str = r#" "#; #[test] -fn test_serde() { +fn test_deserialization() { let did_doc = serde_json::from_str::(DID_DOC_DATA).unwrap(); assert_eq!(did_doc.id().to_string(), "did:sov:HR6vs6GEZ8rHaVgjg2WodM"); assert_eq!(did_doc.verification_method().len(), 2); @@ -136,3 +136,11 @@ fn test_serde() { panic!("Expected reference key kind"); } } + +#[test] +fn test_deserialization_and_serialization() { + let did_doc_1 = serde_json::from_str::(DID_DOC_DATA).unwrap(); + let serialized = serde_json::to_string_pretty(&did_doc_1).unwrap(); + let did_doc_2 = serde_json::from_str::(&serialized).unwrap(); + assert_eq!(did_doc_1, did_doc_2); +}