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

[ref] network-documents: migrate head v3 to text format

parent 4cfc0479
Branches
Tags
1 merge request!93Migrate network documents to pest
...@@ -78,19 +78,22 @@ peer_v11 = ${ "11:" ~ currency ~ ":" ~ node_id ~ ":" ~ pubkey ~ ":" ~ blockstamp ...@@ -78,19 +78,22 @@ peer_v11 = ${ "11:" ~ currency ~ ":" ~ node_id ~ ":" ~ pubkey ~ ":" ~ blockstamp
api_outgoing_conf = @{ u8 } api_outgoing_conf = @{ u8 }
api_incoming_conf = @{ u8 } api_incoming_conf = @{ u8 }
free_member_rooms = @{ u8 } free_member_rooms = @{ u8 }
low_priority_rooms = @{ u8 } free_mirror_rooms = @{ u8 }
software = @{ ASCII_ALPHA ~ ASCII_ALPHANUMERIC* } software = @{ ASCII_ALPHA ~ ASCII_ALPHANUMERIC* }
soft_version = @{ ASCII_DIGIT ~ "." ~ ASCII_DIGIT ~ "." ~ ASCII_DIGIT ~ ("-" ~ ("a" | "b" | "rc") ~ ASCII_DIGIT ~ (ASCII_DIGIT ~ "."){0,2})? } soft_version = @{ ASCII_DIGIT ~ "." ~ ASCII_DIGIT ~ "." ~ ASCII_DIGIT ~ ("-" ~ ("a" | "b" | "rc") ~ ASCII_DIGIT ~ ("." ~ ASCII_DIGIT){0,2})? }
step = @{ u_int }
head_v3_body = ${ head_v3 = ${
"3:" ~ currency ~ ":" ~
api_outgoing_conf ~ ":" ~ api_outgoing_conf ~ ":" ~
api_incoming_conf ~ ":" ~ api_incoming_conf ~ ":" ~
free_member_rooms ~ ":" ~ free_member_rooms ~ ":" ~
low_priority_rooms ~ ":" ~ free_mirror_rooms ~ ":" ~
node_id ~ ":" ~ node_id ~ ":" ~
pubkey ~ ":" ~ pubkey ~ ":" ~
blockstamp ~ ":" ~ blockstamp ~ ":" ~
software ~ ":" ~ software ~ ":" ~
soft_version soft_version ~ nl ~
ed25519_sig? ~
(nl ~ step)?
} }
...@@ -32,7 +32,7 @@ pub enum NetworkHead { ...@@ -32,7 +32,7 @@ pub enum NetworkHead {
/// Head V2 /// Head V2
V2(Box<NetworkHeadV2>), V2(Box<NetworkHeadV2>),
/// head V3 /// head V3
V3(Box<NetworkHeadV3Container>), V3(Box<NetworkHeadV3>),
} }
impl ToString for NetworkHead { impl ToString for NetworkHead {
......
...@@ -17,68 +17,27 @@ ...@@ -17,68 +17,27 @@
use base58::ToBase58; use base58::ToBase58;
use duniter_documents::blockstamp::Blockstamp; use duniter_documents::blockstamp::Blockstamp;
use dup_crypto::keys::bin_signable::BinSignable; use duniter_documents::{BlockHash, BlockId, CurrencyName, ToJsonObject};
use dup_crypto::keys::text_signable::TextSignable;
use dup_crypto::keys::*; use dup_crypto::keys::*;
use serde_json; use pest::iterators::Pair;
use pest::Parser;
use std::cmp::Ordering; use std::cmp::Ordering;
use NodeId; use *;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// Head V3
pub struct NetworkHeadV3Container {
/// Head step
pub step: u8,
/// head body
pub body: NetworkHeadV3,
}
impl PartialOrd for NetworkHeadV3Container {
fn partial_cmp(&self, other: &NetworkHeadV3Container) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for NetworkHeadV3Container {
fn cmp(&self, other: &NetworkHeadV3Container) -> Ordering {
self.body.cmp(&other.body)
}
}
impl NetworkHeadV3Container {
/// Convert to JSON String
pub fn to_json_head(&self) -> Result<String, serde_json::Error> {
Ok(serde_json::to_string_pretty(&JsonHeadV3 {
api_outgoing_conf: self.body.api_outgoing_conf,
api_incoming_conf: self.body.api_incoming_conf,
free_mirror_rooms: self.body.free_mirror_rooms,
low_priority_rooms: self.body.low_priority_rooms,
node_id: self.body.node_id,
algorithm: self.body.pubkey.algo(),
pubkey: self.body.pubkey.to_base58(),
blockstamp: self.body.blockstamp.to_string(),
software: &self.body.software,
soft_version: &self.body.soft_version,
signature: if let Some(sig) = self.body.signature {
Some(sig.to_base64())
} else {
None
},
step: self.step,
})?)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// Head V3 /// Head V3
pub struct NetworkHeadV3 { pub struct NetworkHeadV3 {
/// Currency name
pub currency_name: CurrencyName,
/// WS2P Private configuration /// WS2P Private configuration
pub api_outgoing_conf: u8, pub api_outgoing_conf: u8,
/// WS2P Public configuration /// WS2P Public configuration
pub api_incoming_conf: u8, pub api_incoming_conf: u8,
/// Issuer node free member rooms
pub free_member_rooms: u8,
/// Issuer node free mirror rooms /// Issuer node free mirror rooms
pub free_mirror_rooms: u8, pub free_mirror_rooms: u8,
/// Issuer node free "low priority" rooms
pub low_priority_rooms: u8,
/// Issuer node id /// Issuer node id
pub node_id: NodeId, pub node_id: NodeId,
/// Issuer pubkey /// Issuer pubkey
...@@ -91,6 +50,8 @@ pub struct NetworkHeadV3 { ...@@ -91,6 +50,8 @@ pub struct NetworkHeadV3 {
pub soft_version: String, pub soft_version: String,
/// Issuer signature /// Issuer signature
pub signature: Option<Sig>, pub signature: Option<Sig>,
/// Head step
pub step: u8,
} }
impl PartialOrd for NetworkHeadV3 { impl PartialOrd for NetworkHeadV3 {
...@@ -105,7 +66,34 @@ impl Ord for NetworkHeadV3 { ...@@ -105,7 +66,34 @@ impl Ord for NetworkHeadV3 {
} }
} }
impl<'de> BinSignable<'de> for NetworkHeadV3 { /*impl<'de> BinSignable<'de> for NetworkHeadV3 {
fn issuer_pubkey(&self) -> PubKey {
self.pubkey
}
fn signature(&self) -> Option<Sig> {
self.signature
}
fn set_signature(&mut self, signature: Sig) {
self.signature = Some(signature);
}
}*/
impl TextSignable for NetworkHeadV3 {
fn as_signable_text(&self) -> String {
format!(
"3:{currency}:{api_outgoing_conf}:{api_incoming_conf}:{free_member_rooms}:{free_mirror_rooms}:{node_id}:{pubkey}:{blockstamp}:{software}:{soft_version}\n",
currency = self.currency_name,
api_outgoing_conf = self.api_outgoing_conf,
api_incoming_conf = self.api_incoming_conf,
free_member_rooms = self.free_member_rooms,
free_mirror_rooms = self.free_mirror_rooms,
node_id = format!("{}", self.node_id),
pubkey = self.pubkey.to_base58(),
blockstamp = self.blockstamp.to_string(),
software = self.software,
soft_version = self.soft_version,
)
}
fn issuer_pubkey(&self) -> PubKey { fn issuer_pubkey(&self) -> PubKey {
self.pubkey self.pubkey
} }
...@@ -117,17 +105,93 @@ impl<'de> BinSignable<'de> for NetworkHeadV3 { ...@@ -117,17 +105,93 @@ impl<'de> BinSignable<'de> for NetworkHeadV3 {
} }
} }
impl NetworkHeadV3 {
/// parse from raw ascii format
pub fn parse_from_raw(raw_peer: &str) -> Result<NetworkHeadV3, ParseError> {
match NetworkDocsParser::parse(Rule::head_v3, raw_peer) {
Ok(mut head_v3_pairs) => {
Ok(NetworkHeadV3::from_pest_pair(head_v3_pairs.next().unwrap()))
}
Err(pest_error) => Err(ParseError::PestError(format!("{}", pest_error))),
}
}
/// Generate from pest pair
fn from_pest_pair(pair: Pair<Rule>) -> NetworkHeadV3 {
let mut currency_str = "";
let mut api_outgoing_conf = 0;
let mut api_incoming_conf = 0;
let mut free_member_rooms = 0;
let mut free_mirror_rooms = 0;
let mut node_id = NodeId(0);
let mut pubkey = None;
let mut blockstamp = None;
let mut software = "";
let mut soft_version = "";
let mut signature = None;
let mut step = 0;
for field in pair.into_inner() {
match field.as_rule() {
Rule::currency => currency_str = field.as_str(),
Rule::api_outgoing_conf => api_outgoing_conf = field.as_str().parse().unwrap(),
Rule::api_incoming_conf => api_incoming_conf = field.as_str().parse().unwrap(),
Rule::free_member_rooms => free_member_rooms = field.as_str().parse().unwrap(),
Rule::free_mirror_rooms => free_mirror_rooms = field.as_str().parse().unwrap(),
Rule::node_id => node_id = NodeId(field.as_str().parse().unwrap()),
Rule::pubkey => {
pubkey = Some(PubKey::Ed25519(
ed25519::PublicKey::from_base58(field.as_str()).unwrap(),
))
}
Rule::blockstamp => {
let mut inner_rules = field.into_inner(); // { block_id ~ "-" ~ hash }
let block_id: &str = inner_rules.next().unwrap().as_str();
let block_hash: &str = inner_rules.next().unwrap().as_str();
blockstamp = Some(Blockstamp {
id: BlockId(block_id.parse().unwrap()), // Grammar ensures that we have a digits string.
hash: BlockHash(Hash::from_hex(block_hash).unwrap()), // Grammar ensures that we have an hexadecimal string.
});
}
Rule::software => software = field.as_str(),
Rule::soft_version => soft_version = field.as_str(),
Rule::ed25519_sig => {
signature = Some(Sig::Ed25519(
ed25519::Signature::from_base64(field.as_str()).unwrap(),
))
}
Rule::step => step = field.as_str().parse().unwrap(),
_ => panic!("unexpected rule: {:?}", field.as_rule()), // Grammar ensures that we never reach this line
}
}
NetworkHeadV3 {
currency_name: CurrencyName(currency_str.to_owned()),
api_outgoing_conf,
api_incoming_conf,
free_member_rooms,
free_mirror_rooms,
node_id,
pubkey: pubkey.expect("Grammar must ensure that head v3 have valid issuer pubkey !"),
blockstamp: blockstamp
.expect("Grammar must ensure that head v3 have valid blockstamp!"),
software: software.to_owned(),
soft_version: soft_version.to_owned(),
signature,
step,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// Head V3 for json serializer /// Head V3 for json serializer
pub struct JsonHeadV3<'a> { pub struct JsonHeadV3 {
/// WS2P Private configuration /// WS2P Private configuration
pub api_outgoing_conf: u8, pub api_outgoing_conf: u8,
/// WS2P Public configuration /// WS2P Public configuration
pub api_incoming_conf: u8, pub api_incoming_conf: u8,
/// Issuer node free member rooms
pub free_member_rooms: u8,
/// Issuer node free mirror rooms /// Issuer node free mirror rooms
pub free_mirror_rooms: u8, pub free_mirror_rooms: u8,
/// Issuer node free "low priority" rooms
pub low_priority_rooms: u8,
/// Issuer node id /// Issuer node id
pub node_id: NodeId, pub node_id: NodeId,
/// Issuer key algorithm /// Issuer key algorithm
...@@ -137,33 +201,56 @@ pub struct JsonHeadV3<'a> { ...@@ -137,33 +201,56 @@ pub struct JsonHeadV3<'a> {
/// Head blockstamp /// Head blockstamp
pub blockstamp: String, pub blockstamp: String,
/// Issuer node software /// Issuer node software
pub software: &'a str, pub software: String,
/// Issuer node soft version /// Issuer node soft version
pub soft_version: &'a str, pub soft_version: String,
/// Issuer signature /// Issuer signature
pub signature: Option<String>, pub signature: Option<String>,
/// Head step /// Head step
pub step: u8, pub step: u8,
} }
impl<'a> ToJsonObject for NetworkHeadV3 {
type JsonObject = JsonHeadV3;
fn to_json_object(&self) -> Self::JsonObject {
JsonHeadV3 {
api_outgoing_conf: self.api_outgoing_conf,
api_incoming_conf: self.api_incoming_conf,
free_member_rooms: self.free_member_rooms,
free_mirror_rooms: self.free_mirror_rooms,
node_id: self.node_id,
algorithm: self.pubkey.algo(),
pubkey: self.pubkey.to_base58(),
blockstamp: self.blockstamp.to_string(),
software: self.software.clone(),
soft_version: self.soft_version.clone(),
signature: if let Some(sig) = self.signature {
Some(sig.to_base64())
} else {
None
},
step: self.step,
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use dup_crypto::keys::bin_signable::BinSignable;
use tests::bincode::deserialize;
use tests::keypair1; use tests::keypair1;
#[test] #[test]
fn head_v3_sign_and_verify() { fn head_v3_sign_and_verify() {
let mut head_v3 = NetworkHeadV3Container { let keypair = keypair1();
step: 0, let mut head_v3 = NetworkHeadV3 {
body: NetworkHeadV3 { currency_name: CurrencyName("g1".to_owned()),
api_outgoing_conf: 0u8, api_outgoing_conf: 0u8,
api_incoming_conf: 0u8, api_incoming_conf: 0u8,
free_mirror_rooms: 0u8, free_mirror_rooms: 0u8,
low_priority_rooms: 0u8, free_member_rooms: 0u8,
node_id: NodeId(0), node_id: NodeId(0),
pubkey: PubKey::Ed25519(keypair1().public_key()), pubkey: PubKey::Ed25519(keypair.public_key()),
blockstamp: Blockstamp::from_string( blockstamp: Blockstamp::from_string(
"50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370", "50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370",
) )
...@@ -171,23 +258,20 @@ mod tests { ...@@ -171,23 +258,20 @@ mod tests {
software: String::from("durs"), software: String::from("durs"),
soft_version: String::from("0.1.0-a0.1"), soft_version: String::from("0.1.0-a0.1"),
signature: None, signature: None,
}, step: 0,
}; };
// Sign // Sign
let sign_result = head_v3 let sign_result = head_v3.sign(PrivKey::Ed25519(keypair.private_key()));
.body if let Ok(head_v3_raw) = sign_result {
.sign(PrivKey::Ed25519(keypair1().private_key())); println!("{}", head_v3_raw);
if let Ok(head_v3_body_bytes) = sign_result { assert_eq!(
let deser_head_v3_body: NetworkHeadV3 = head_v3,
deserialize(&head_v3_body_bytes).expect("Fail to deserialize PeerCardV11 !"); NetworkHeadV3::parse_from_raw(&head_v3_raw).expect("Fail to parse head v3 !")
assert_eq!(head_v3.body, deser_head_v3_body,) )
} else { } else {
panic!("failt to sign head v3 : {:?}", sign_result.err().unwrap()) panic!("fail to sign head v3 : {:?}", sign_result.err().unwrap())
} }
// Verify signature // Verify signature
head_v3.body.verify().expect("HEADv3 : Invalid signature !"); head_v3.verify().expect("HEADv3 : Invalid signature !");
//let json_head_v3 = head_v3.to_json_head().expect("Fail to serialize HEAD v3 !");
//println!("{}", json_head_v3);
//panic!();
} }
} }
...@@ -26,7 +26,7 @@ use duniter_documents::v10::revocation::RevocationDocument; ...@@ -26,7 +26,7 @@ use duniter_documents::v10::revocation::RevocationDocument;
use duniter_documents::v10::transaction::TransactionDocument; use duniter_documents::v10::transaction::TransactionDocument;
use dup_crypto::hashs::Hash; use dup_crypto::hashs::Hash;
use durs_network_documents::network_head_v2::NetworkHeadV2; use durs_network_documents::network_head_v2::NetworkHeadV2;
use durs_network_documents::network_head_v3::NetworkHeadV3Container; use durs_network_documents::network_head_v3::NetworkHeadV3;
use durs_network_documents::network_peer::PeerCardV11; use durs_network_documents::network_peer::PeerCardV11;
/// WS2P v2 message payload metadata size /// WS2P v2 message payload metadata size
...@@ -54,7 +54,7 @@ pub enum WS2Pv0MessagePayload { ...@@ -54,7 +54,7 @@ pub enum WS2Pv0MessagePayload {
/// HEADS_V2 Message /// HEADS_V2 Message
Headsv2(Vec<NetworkHeadV2>), Headsv2(Vec<NetworkHeadV2>),
/// HEADS_V3 Message /// HEADS_V3 Message
Heads3(Vec<NetworkHeadV3Container>), Heads3(Vec<NetworkHeadV3>),
/// BLOCKS Message /// BLOCKS Message
Blocks(Vec<BlockDocument>), Blocks(Vec<BlockDocument>),
/// PENDING_IDENTITIES Message /// PENDING_IDENTITIES Message
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment