diff --git a/documents/blockchain/v10/documents/certification.rs b/documents/blockchain/v10/documents/certification.rs index d4de8631c1078f587aba3679dbe8328c294b82ac..46a4467fd11853a1ff10f24ae86304546bbedd1d 100644 --- a/documents/blockchain/v10/documents/certification.rs +++ b/documents/blockchain/v10/documents/certification.rs @@ -191,6 +191,16 @@ CertTimestamp: {blockstamp} blockstamp = self.blockstamp, ) } + + fn generate_compact_text(&self, signatures: Vec<ed25519::Signature>) -> String { + format!( + "{issuer}:{target}:{block_number}:{signature}", + issuer = self.issuer, + target = self.target, + block_number = self.blockstamp.id.0, + signature = signatures[0], + ) + } } /// Certification document parser @@ -297,6 +307,12 @@ mod tests { builder.build_and_sign(vec![prikey]).verify_signatures(), VerificationResult::Valid() ); + assert_eq!( + builder.generate_compact_text(vec![sig]), + "4tNQ7d9pj2Da5wUVoW9mFn7JjuPoowF977au8DdhEjVR:\ + DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:36:\ + qfR6zqT1oJbqIsppOi64gC9yTtxb6g6XA9RYpulkq9ehMvqg2VYVigCbR0yVpqKFsnYiQTrnjgFuFRSJCJDfCw==" + ); } #[test] diff --git a/documents/blockchain/v10/documents/identity.rs b/documents/blockchain/v10/documents/identity.rs index ac7622ec78cb27ce47dfb36c28668dd7f2980b35..855d620557fb0abd8f9add187d5c3da157afeaa6 100644 --- a/documents/blockchain/v10/documents/identity.rs +++ b/documents/blockchain/v10/documents/identity.rs @@ -43,7 +43,7 @@ pub struct IdentityDocument { /// Currency. currency: String, /// Unique ID - unique_id: String, + username: String, /// Blockstamp blockstamp: Blockstamp, /// Document issuer (there should be only one). @@ -54,8 +54,8 @@ pub struct IdentityDocument { impl IdentityDocument { /// Unique ID - pub fn unique_id(&self) -> &str { - &self.unique_id + pub fn username(&self) -> &str { + &self.username } } @@ -102,7 +102,7 @@ pub struct IdentityDocumentBuilder<'a> { /// Document currency. pub currency: &'a str, /// Identity unique id. - pub unique_id: &'a str, + pub username: &'a str, /// Reference blockstamp. pub blockstamp: &'a Blockstamp, /// Document/identity issuer. @@ -118,7 +118,7 @@ impl<'a> IdentityDocumentBuilder<'a> { IdentityDocument { text, currency: self.currency.to_string(), - unique_id: self.unique_id.to_string(), + username: self.username.to_string(), blockstamp: *self.blockstamp, issuers: vec![*self.issuer], signatures, @@ -147,15 +147,25 @@ impl<'a> TextDocumentBuilder for IdentityDocumentBuilder<'a> { Type: Identity Currency: {currency} Issuer: {issuer} -UniqueID: {unique_id} +UniqueID: {username} Timestamp: {blockstamp} ", currency = self.currency, issuer = self.issuer, - unique_id = self.unique_id, + username = self.username, blockstamp = self.blockstamp ) } + + fn generate_compact_text(&self, signatures: Vec<ed25519::Signature>) -> String { + format!( + "{issuer}:{signature}:{blockstamp}:{username}", + issuer = self.issuer, + signature = signatures[0], + blockstamp = self.blockstamp, + username = self.username, + ) + } } /// Identity document parser @@ -182,7 +192,7 @@ impl StandardTextDocumentParser for IdentityDocumentParser { Ok(V10Document::Identity(IdentityDocument { text: doc.to_owned(), currency: currency.to_owned(), - unique_id: uid.to_owned(), + username: uid.to_owned(), blockstamp, issuers: vec![issuer], signatures, @@ -223,7 +233,7 @@ mod tests { let builder = IdentityDocumentBuilder { currency: "duniter_unit_test_currency", - unique_id: "tic", + username: "tic", blockstamp: &block, issuer: &pubkey, }; diff --git a/documents/blockchain/v10/documents/membership.rs b/documents/blockchain/v10/documents/membership.rs index 0fab5443d53f047616407afbc153dc491c60289d..9b9d41668d5e36940d14d5e0b4466427298353a8 100644 --- a/documents/blockchain/v10/documents/membership.rs +++ b/documents/blockchain/v10/documents/membership.rs @@ -190,6 +190,17 @@ CertTS: {ity_blockstamp} ity_blockstamp = self.identity_blockstamp, ) } + + fn generate_compact_text(&self, signatures: Vec<ed25519::Signature>) -> String { + format!( + "{issuer}:{signature}:{blockstamp}:{idty_blockstamp}:{username}", + issuer = self.issuer, + signature = signatures[0], + blockstamp = self.blockstamp, + idty_blockstamp = self.identity_blockstamp, + username = self.identity_username, + ) + } } /// Membership document parser @@ -284,6 +295,14 @@ mod tests { builder.build_and_sign(vec![prikey]).verify_signatures(), VerificationResult::Valid() ); + assert_eq!( + builder.generate_compact_text(vec![sig]), + "DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:\ + s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkElAyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw==:\ + 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:\ + 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:\ + tic" + ); } #[test] diff --git a/documents/blockchain/v10/documents/mod.rs b/documents/blockchain/v10/documents/mod.rs index 50fd7d67f110afd55bb7890cc67f985855655f7c..8a02f2ee0cdfb65debe2d972ebc944e57f75da06 100644 --- a/documents/blockchain/v10/documents/mod.rs +++ b/documents/blockchain/v10/documents/mod.rs @@ -105,6 +105,13 @@ pub trait TextDocumentBuilder: DocumentBuilder { /// - Contains line breaks on all line. fn generate_text(&self) -> String; + /// Generate document compact text. + /// the compact format is the one used in the blocks. + /// + /// - Don't contains leading signatures + /// - Contains line breaks on all line. + fn generate_compact_text(&self, signatures: Vec<ed25519::Signature>) -> String; + /// Generate final document with signatures, and also return them in an array. /// /// Returns : @@ -164,15 +171,6 @@ trait StandardTextDocumentParser { ) -> Result<V10Document, V10DocumentParsingError>; } -trait CompactTextDocumentParser<D: TextDocument> { - fn parse_compact( - doc: &str, - body: &str, - currency: &str, - signatures: Vec<ed25519::Signature>, - ) -> Result<D, V10DocumentParsingError>; -} - /// A V10 document parser. #[derive(Debug, Clone, Copy)] pub struct V10DocumentParser; @@ -298,11 +296,11 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN fn parse_identity_document() { let text = "Version: 10 Type: Identity -Currency: duniter_unit_test_currency -Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV -UniqueID: tic +Currency: g1 +Issuer: D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx +UniqueID: elois Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 -1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg=="; +Ydnclvw76/JHcKSmU9kl9Ie0ne5/X8NYOqPqbGnufIK3eEPRYYdEYaQh+zffuFhbtIRjv6m/DkVLH5cLy/IyAg=="; let doc = V10DocumentParser::parse(text).unwrap(); if let V10Document::Identity(doc) = doc { @@ -317,13 +315,13 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 fn parse_membership_document() { let text = "Version: 10 Type: Membership -Currency: duniter_unit_test_currency -Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV +Currency: g1 +Issuer: D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx Block: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 Membership: IN -UserID: tic +UserID: elois CertTS: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 -s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkElAyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw=="; +FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg=="; let doc = V10DocumentParser::parse(text).unwrap(); if let V10Document::Membership(doc) = doc { diff --git a/documents/blockchain/v10/documents/revocation.rs b/documents/blockchain/v10/documents/revocation.rs index 6b7538b9c472913d74821518400a7ce985e9e077..3760f6369157a7044318ee0d5a56f13c513ed10d 100644 --- a/documents/blockchain/v10/documents/revocation.rs +++ b/documents/blockchain/v10/documents/revocation.rs @@ -165,6 +165,13 @@ IdtySignature: {idty_sig} idty_sig = self.identity_sig, ) } + fn generate_compact_text(&self, signatures: Vec<ed25519::Signature>) -> String { + format!( + "{issuer}:{signature}", + issuer = self.issuer, + signature = signatures[0], + ) + } } /// Revocation document parser diff --git a/documents/blockchain/v10/documents/transaction.rs b/documents/blockchain/v10/documents/transaction.rs index a1a786549705144d43531a8796d16da903bcd74c..e44ce2e33d4dbc225d44f75bc7a9242661a033fa 100644 --- a/documents/blockchain/v10/documents/transaction.rs +++ b/documents/blockchain/v10/documents/transaction.rs @@ -535,6 +535,52 @@ Issuers: comment = self.comment, ) } + + fn generate_compact_text(&self, signatures: Vec<ed25519::Signature>) -> String { + let mut issuers_str = String::from(""); + for issuer in self.issuers { + issuers_str.push_str(&issuer.to_string()); + } + let mut inputs_str = String::from(""); + for input in self.inputs { + inputs_str.push_str(&input.to_string()); + } + let mut unlocks_str = String::from(""); + for unlock in self.unlocks { + unlocks_str.push_str(&unlock.to_string()); + } + let mut outputs_str = String::from(""); + for output in self.outputs { + outputs_str.push_str(&output.to_string()); + } + let mut signatures_str = String::from(""); + for sig in signatures { + signatures_str.push_str(&sig.to_string()); + } + format!( + "TX:10:{issuers_count}:{inputs_count}:{unlocks_count}:{outputs_count}:{has_comment}:{locktime} +{blockstamp} +{issuers} +{inputs} +{unlocks} +{outputs} +{comment} +{signatures}", + issuers_count = self.issuers.len(), + inputs_count = self.inputs.len(), + unlocks_count = self.unlocks.len(), + outputs_count = self.outputs.len(), + has_comment = if self.comment.is_empty() { 0 } else { 1 }, + locktime = self.locktime, + blockstamp = self.blockstamp, + issuers = issuers_str, + inputs = inputs_str, + unlocks = unlocks_str, + outputs = outputs_str, + comment = self.comment, + signatures = signatures_str, + ) + } } /// Transaction document parser @@ -553,20 +599,18 @@ impl StandardTextDocumentParser for TransactionDocumentParser { .build() .expect("fail to build TRANSACTION_REGEX !"); if let Some(caps) = tx_regex.captures(body) { - let blockstamp = &caps["blockstamp"]; - let locktime = &caps["locktime"]; - let issuers_string = &caps["issuers"]; + let blockstamp = + Blockstamp::from_string(&caps["blockstamp"]).expect("fail to parse blockstamp"); + let locktime = caps["locktime"].parse().expect("fail to parse locktime"); + let issuers_str = &caps["issuers"]; let inputs = &caps["inputs"]; let unlocks = &caps["unlocks"]; let outputs = &caps["outputs"]; - let comment = &caps["comment"]; + let comment = String::from(&caps["comment"]); - // Regex match so should not fail. - // TODO : Test it anyway - let blockstamp = Blockstamp::from_string(blockstamp).expect("fail to parse blockstamp"); - let locktime = locktime.parse().expect("fail to parse locktime"); let mut issuers = Vec::new(); - for caps in ISSUER_REGEX.captures_iter(issuers_string) { + for caps in ISSUER_REGEX.captures_iter(issuers_str) { + println!("{:?}", &caps["issuer"]); issuers.push( ed25519::PublicKey::from_base58(&caps["issuer"]).expect("fail to parse issuer"), ); @@ -592,8 +636,6 @@ impl StandardTextDocumentParser for TransactionDocumentParser { outputs.push(TransactionOuput::parse_from_str(output)?); } } - let comment = String::from(comment); - // let re = Regex::new(r"[ \t]+").unwrap(); Ok(V10Document::Transaction(Box::new(TransactionDocument { text: doc.to_owned(), @@ -673,6 +715,18 @@ mod tests { builder.build_and_sign(vec![prikey]).verify_signatures(), VerificationResult::Valid() ); + + assert_eq!( + builder.generate_compact_text(vec![sig]), + "TX:10:1:1:1:1:1:0 +0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 +DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV +10:0:D:DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:0 +0:SIG(0) +10:0:SIG(FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa) +test +pRQeKlzCsvPNmYAAkEP5jPPQO1RwrtFMRfCajEfkkrG0UQE0DhoTkxG3Zs2JFmvAFLw67pn1V5NQ08zsSfJkBg==" + ); } #[test]