Skip to content
Snippets Groups Projects
Commit b241b382 authored by Éloïs's avatar Éloïs
Browse files

[enh] add generate compact format for all documents

parent 0731c362
No related branches found
No related tags found
1 merge request!41Resolve "Add Transaction document structure, building and parsing"
...@@ -191,6 +191,16 @@ CertTimestamp: {blockstamp} ...@@ -191,6 +191,16 @@ CertTimestamp: {blockstamp}
blockstamp = self.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 /// Certification document parser
...@@ -297,6 +307,12 @@ mod tests { ...@@ -297,6 +307,12 @@ mod tests {
builder.build_and_sign(vec![prikey]).verify_signatures(), builder.build_and_sign(vec![prikey]).verify_signatures(),
VerificationResult::Valid() VerificationResult::Valid()
); );
assert_eq!(
builder.generate_compact_text(vec![sig]),
"4tNQ7d9pj2Da5wUVoW9mFn7JjuPoowF977au8DdhEjVR:\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:36:\
qfR6zqT1oJbqIsppOi64gC9yTtxb6g6XA9RYpulkq9ehMvqg2VYVigCbR0yVpqKFsnYiQTrnjgFuFRSJCJDfCw=="
);
} }
#[test] #[test]
......
...@@ -43,7 +43,7 @@ pub struct IdentityDocument { ...@@ -43,7 +43,7 @@ pub struct IdentityDocument {
/// Currency. /// Currency.
currency: String, currency: String,
/// Unique ID /// Unique ID
unique_id: String, username: String,
/// Blockstamp /// Blockstamp
blockstamp: Blockstamp, blockstamp: Blockstamp,
/// Document issuer (there should be only one). /// Document issuer (there should be only one).
...@@ -54,8 +54,8 @@ pub struct IdentityDocument { ...@@ -54,8 +54,8 @@ pub struct IdentityDocument {
impl IdentityDocument { impl IdentityDocument {
/// Unique ID /// Unique ID
pub fn unique_id(&self) -> &str { pub fn username(&self) -> &str {
&self.unique_id &self.username
} }
} }
...@@ -102,7 +102,7 @@ pub struct IdentityDocumentBuilder<'a> { ...@@ -102,7 +102,7 @@ pub struct IdentityDocumentBuilder<'a> {
/// Document currency. /// Document currency.
pub currency: &'a str, pub currency: &'a str,
/// Identity unique id. /// Identity unique id.
pub unique_id: &'a str, pub username: &'a str,
/// Reference blockstamp. /// Reference blockstamp.
pub blockstamp: &'a Blockstamp, pub blockstamp: &'a Blockstamp,
/// Document/identity issuer. /// Document/identity issuer.
...@@ -118,7 +118,7 @@ impl<'a> IdentityDocumentBuilder<'a> { ...@@ -118,7 +118,7 @@ impl<'a> IdentityDocumentBuilder<'a> {
IdentityDocument { IdentityDocument {
text, text,
currency: self.currency.to_string(), currency: self.currency.to_string(),
unique_id: self.unique_id.to_string(), username: self.username.to_string(),
blockstamp: *self.blockstamp, blockstamp: *self.blockstamp,
issuers: vec![*self.issuer], issuers: vec![*self.issuer],
signatures, signatures,
...@@ -147,15 +147,25 @@ impl<'a> TextDocumentBuilder for IdentityDocumentBuilder<'a> { ...@@ -147,15 +147,25 @@ impl<'a> TextDocumentBuilder for IdentityDocumentBuilder<'a> {
Type: Identity Type: Identity
Currency: {currency} Currency: {currency}
Issuer: {issuer} Issuer: {issuer}
UniqueID: {unique_id} UniqueID: {username}
Timestamp: {blockstamp} Timestamp: {blockstamp}
", ",
currency = self.currency, currency = self.currency,
issuer = self.issuer, issuer = self.issuer,
unique_id = self.unique_id, username = self.username,
blockstamp = self.blockstamp 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 /// Identity document parser
...@@ -182,7 +192,7 @@ impl StandardTextDocumentParser for IdentityDocumentParser { ...@@ -182,7 +192,7 @@ impl StandardTextDocumentParser for IdentityDocumentParser {
Ok(V10Document::Identity(IdentityDocument { Ok(V10Document::Identity(IdentityDocument {
text: doc.to_owned(), text: doc.to_owned(),
currency: currency.to_owned(), currency: currency.to_owned(),
unique_id: uid.to_owned(), username: uid.to_owned(),
blockstamp, blockstamp,
issuers: vec![issuer], issuers: vec![issuer],
signatures, signatures,
...@@ -223,7 +233,7 @@ mod tests { ...@@ -223,7 +233,7 @@ mod tests {
let builder = IdentityDocumentBuilder { let builder = IdentityDocumentBuilder {
currency: "duniter_unit_test_currency", currency: "duniter_unit_test_currency",
unique_id: "tic", username: "tic",
blockstamp: &block, blockstamp: &block,
issuer: &pubkey, issuer: &pubkey,
}; };
......
...@@ -190,6 +190,17 @@ CertTS: {ity_blockstamp} ...@@ -190,6 +190,17 @@ CertTS: {ity_blockstamp}
ity_blockstamp = self.identity_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 /// Membership document parser
...@@ -284,6 +295,14 @@ mod tests { ...@@ -284,6 +295,14 @@ mod tests {
builder.build_and_sign(vec![prikey]).verify_signatures(), builder.build_and_sign(vec![prikey]).verify_signatures(),
VerificationResult::Valid() VerificationResult::Valid()
); );
assert_eq!(
builder.generate_compact_text(vec![sig]),
"DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:\
s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkElAyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw==:\
0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:\
0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:\
tic"
);
} }
#[test] #[test]
......
...@@ -105,6 +105,13 @@ pub trait TextDocumentBuilder: DocumentBuilder { ...@@ -105,6 +105,13 @@ pub trait TextDocumentBuilder: DocumentBuilder {
/// - Contains line breaks on all line. /// - Contains line breaks on all line.
fn generate_text(&self) -> String; 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. /// Generate final document with signatures, and also return them in an array.
/// ///
/// Returns : /// Returns :
...@@ -164,15 +171,6 @@ trait StandardTextDocumentParser { ...@@ -164,15 +171,6 @@ trait StandardTextDocumentParser {
) -> Result<V10Document, V10DocumentParsingError>; ) -> 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. /// A V10 document parser.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct V10DocumentParser; pub struct V10DocumentParser;
...@@ -298,11 +296,11 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN ...@@ -298,11 +296,11 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN
fn parse_identity_document() { fn parse_identity_document() {
let text = "Version: 10 let text = "Version: 10
Type: Identity Type: Identity
Currency: duniter_unit_test_currency Currency: g1
Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV Issuer: D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx
UniqueID: tic UniqueID: elois
Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg=="; Ydnclvw76/JHcKSmU9kl9Ie0ne5/X8NYOqPqbGnufIK3eEPRYYdEYaQh+zffuFhbtIRjv6m/DkVLH5cLy/IyAg==";
let doc = V10DocumentParser::parse(text).unwrap(); let doc = V10DocumentParser::parse(text).unwrap();
if let V10Document::Identity(doc) = doc { if let V10Document::Identity(doc) = doc {
...@@ -317,13 +315,13 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 ...@@ -317,13 +315,13 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
fn parse_membership_document() { fn parse_membership_document() {
let text = "Version: 10 let text = "Version: 10
Type: Membership Type: Membership
Currency: duniter_unit_test_currency Currency: g1
Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV Issuer: D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx
Block: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 Block: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
Membership: IN Membership: IN
UserID: tic UserID: elois
CertTS: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 CertTS: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkElAyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw=="; FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==";
let doc = V10DocumentParser::parse(text).unwrap(); let doc = V10DocumentParser::parse(text).unwrap();
if let V10Document::Membership(doc) = doc { if let V10Document::Membership(doc) = doc {
......
...@@ -165,6 +165,13 @@ IdtySignature: {idty_sig} ...@@ -165,6 +165,13 @@ IdtySignature: {idty_sig}
idty_sig = self.identity_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 /// Revocation document parser
......
...@@ -535,6 +535,52 @@ Issuers: ...@@ -535,6 +535,52 @@ Issuers:
comment = self.comment, 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 /// Transaction document parser
...@@ -553,20 +599,18 @@ impl StandardTextDocumentParser for TransactionDocumentParser { ...@@ -553,20 +599,18 @@ impl StandardTextDocumentParser for TransactionDocumentParser {
.build() .build()
.expect("fail to build TRANSACTION_REGEX !"); .expect("fail to build TRANSACTION_REGEX !");
if let Some(caps) = tx_regex.captures(body) { if let Some(caps) = tx_regex.captures(body) {
let blockstamp = &caps["blockstamp"]; let blockstamp =
let locktime = &caps["locktime"]; Blockstamp::from_string(&caps["blockstamp"]).expect("fail to parse blockstamp");
let issuers_string = &caps["issuers"]; let locktime = caps["locktime"].parse().expect("fail to parse locktime");
let issuers_str = &caps["issuers"];
let inputs = &caps["inputs"]; let inputs = &caps["inputs"];
let unlocks = &caps["unlocks"]; let unlocks = &caps["unlocks"];
let outputs = &caps["outputs"]; 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(); 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( issuers.push(
ed25519::PublicKey::from_base58(&caps["issuer"]).expect("fail to parse issuer"), ed25519::PublicKey::from_base58(&caps["issuer"]).expect("fail to parse issuer"),
); );
...@@ -592,8 +636,6 @@ impl StandardTextDocumentParser for TransactionDocumentParser { ...@@ -592,8 +636,6 @@ impl StandardTextDocumentParser for TransactionDocumentParser {
outputs.push(TransactionOuput::parse_from_str(output)?); 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 { Ok(V10Document::Transaction(Box::new(TransactionDocument {
text: doc.to_owned(), text: doc.to_owned(),
...@@ -673,6 +715,18 @@ mod tests { ...@@ -673,6 +715,18 @@ mod tests {
builder.build_and_sign(vec![prikey]).verify_signatures(), builder.build_and_sign(vec![prikey]).verify_signatures(),
VerificationResult::Valid() 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] #[test]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment