From 0e9efebd68f8f0cd804f05e3cf42645149bba808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89lo=C3=AFs?= <elois@ifee.fr>
Date: Sun, 11 Nov 2018 19:19:59 +0100
Subject: [PATCH] [ref] ws2pv2: create raw format for peer and head

---
 rfc/0006_ws2p_v2.md | 198 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 177 insertions(+), 21 deletions(-)

diff --git a/rfc/0006_ws2p_v2.md b/rfc/0006_ws2p_v2.md
index 900a20b..e18bd5a 100644
--- a/rfc/0006_ws2p_v2.md
+++ b/rfc/0006_ws2p_v2.md
@@ -25,6 +25,7 @@ We are also taking advantage of these changes to address minor issues :
   * [Why not a total binarization?](#why-not-a-total-binarization)
   * [What consequences for clients softwares ?](#what-consequences-for-clients-softwares)
 * [Conventions](#conventions)
+  * [Raw format](#raw-format)
   * [JSON format](#json-format)
   * [Binary format](#binary-format)
     * [Primitive types](#primitive-types)
@@ -35,7 +36,7 @@ We are also taking advantage of these changes to address minor issues :
   * [Endpoint binary format](#endpoint-binary-format)
   * [Endpoint utf8 format](#endpoint-utf8-format)
 * [Peer card](#peer-card)
-  * [Peer card Binary format](#peer-card-binary-format)
+  * [Peer card Raw format](#peer-card-raw-format)
   * [Peer card JSON format](#peer-card-json-format)
   * [Getting peer cards from other Duniter nodes](#getting-peer-cards-from-other-duniter-nodes)
 * [Priority of WS2P outcoming connections](#priority-of-ws2p-outcoming-connections)
@@ -106,6 +107,18 @@ Finally, users associating external endpoints to their peer cards will have to r
 
 ## Conventions
 
+### Raw format
+
+All documents in raw format are explained via a [PEG grammar].  
+The raw format is a plain text format used to sign a document or verify its signature.  
+Only documents whose signature must be verifiable by a client software are signed in this way. This applies in particular to peer cards and HEADs.  
+WS2pV2 messages are signed in binary format.
+
+The PEG grammars of raw formats are presented according to the [pest syntax] (a particular implementation of PEG).
+
+[PEG grammar]: https://en.wikipedia.org/wiki/Parsing_expression_grammar
+[pest syntax]: https://pest.rs/book/grammars/syntax.html
+
 ### JSON format
 
 All data in JSON format is presented in this RFC with explicit typing.
@@ -139,7 +152,7 @@ i16 : Signed 16-bit integer.
 i32 : Signed 32-bit integer.  
 i64 : Signed 64-bit integer.  
 bool : boolean stored on 8 bits (0x00 = false, 0x01 = true, any other value must generate an error).
-0 : Corresponds to data that must be filled with bits to zero (for example padding).    
+0 : Corresponds to data that must be filled with bits to zero (for example padding).
 
 #### Useful non-primitive types
 
@@ -393,6 +406,83 @@ Signed document declaring all the endpoints of a peer.
 The document is represented by an array of bytes containing (peer_card_size + 2) bytes.  
 to sign the document it is necessary to calculate the hash sha256 of this bytes array then to sign the hash obtained with the issuer's private key.
 
+### Peer card Raw format
+
+Approximate description :
+
+    VERSION:CURRENCY:NODE_ID:PUBLIC_KEY:BLOCKSTAMP
+    ENDPOINT 1
+    ...
+    ENDPOINT n
+    SIGNATURE
+
+_/!\ This description is approximate, it allows you to quickly understand the format but is not authoritative for developing a code to parse the format exactly. If you want to develop a code using this format, please refer to its PEG grammar._
+
+Example :
+
+    11:g1:0:7iMV3b6j2hSj5WtrfchfvxivS9swN3opDgxudeHq64fb:50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370
+    WS2P V2 S 7 g1.durs.ifee.fr 443 ws2p
+    WS2P V2 S 7 84.16.72.210 443 ws2p
+    EQ2D5almq2RNUi3XZNtTpjo9nWtJF0PzsCW7ROAzCQKiEtpI7/fW8Z23GJ2a/SIxfYSzlq/cZqksE4EoVe1rAw==
+
+Peer card v11 PEG grammar :
+
+    ```
+    // Single character rules
+    nl = _{ "\n" }
+    no_zero_hexa_lower = @{ '1'..'9' | 'a'..'f' }
+    hexa_lower = @{ ASCII_DIGIT | 'a'..'f' }
+    hexa_upper = @{ ASCII_DIGIT | 'A'..'F' }
+    base58 = { !("O" | "I" | "l") ~ ASCII_ALPHANUMERIC }
+    base64 = { ASCII_ALPHANUMERIC | "+" | "/" }
+
+    // Numbers rules
+    tens = @{ '1'..'9' ~ ASCII_DIGIT }
+    u8_hundreds = @{ ("2" ~ ('0'..'4' ~ ASCII_DIGIT | ('0'..'5'){2})) | ("1" ~ ASCII_DIGIT{2}) }
+    u8 = @{ u8_hundreds | tens | ASCII_DIGIT }
+    no_zero_u_int = @{ '1'..'9' ~ ASCII_DIGIT* }
+    u_int = @{ "0" | no_zero_u_int }
+
+    // Usefull types rules
+    currency = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "-" | "_"){,255} }
+    block_id = @{ u_int }
+    hash = @{ hexa_upper{64} }
+    pubkey = @{ base58{43,44} }
+    blockstamp =  ${ block_id ~ "-" ~ hash }
+    ed25519_sig = @{ base64{88} | (base64{87} ~ "=") | (base64{86} ~ "==") }
+
+    // IP v6 rules
+    ip6_seg  = _{ hexa_lower{1,4} }
+    ip6_full = _{ (ip6_seg ~ ":"){7} ~ ip6_seg }
+    ip6_no_full = @{
+        ip6_seg? ~
+        (":" ~ ip6_seg){0,6} ~
+        "::" ~
+        (ip6_seg ~ ":"){0,6} ~
+        ip6_seg?
+    }
+    ip6_inner = @{ ip6_full | ip6_no_full }
+    ip6 = _{ "[" ~ ip6_inner ~ "] " }
+
+    // Endpoint v2 rules
+    api_version_inner = @{ no_zero_u_int }
+    api_version = _{ "V" ~ api_version_inner ~ " " }
+    tls = @{ "S " }
+    tor = @{ "TOR " }
+    network_features = _{ tls? ~ tor? }
+    api_features_inner = @{ (hexa_lower{2})+ | no_zero_hexa_lower }
+    api_features = _{ api_features_inner ~ " " }
+    host_v2_inner = @{ ASCII_ALPHA_LOWER ~ (ASCII_ALPHA_LOWER | ASCII_DIGIT | "-" | "_" | ".")* }
+    host_v2 = _{ host_v2_inner ~ " " }
+    ip4_inner = { u8 ~ "." ~ u8 ~ "." ~ u8 ~ "." ~ u8 }
+    ip4 = _{ ip4_inner ~ " " }
+    path = _{ " " ~ path_inner }
+    endpoint_v2 = ${ api_name ~ " " ~ (api_version)? ~ (network_features)? ~ (api_features)? ~ host_v2? ~ ip4? ~ ip6? ~ port ~ path? }
+
+    // Peer v11 rules
+    peer_v11 = ${ "11:" ~ currency ~ ":" ~ node_id ~ ":" ~ pubkey ~ ":" ~ blockstamp ~ nl ~ (endpoint_v2 ~ nl)+ ~ ed25519_sig? }
+    ```
+
 ### Peer card JSON format
 
 This human-readable format will be used by all APIs that wish to provide peer cards in a human-readable format. For example, Client APIs.
@@ -771,25 +861,6 @@ signature := Direct signature of the byte vector from `software_size` to `soft_v
 
 step := Number of head rebounds (unsigned field).
 
-#### HEAD v3 JSON format
-
-This human-readable format will be used by all APIs that wish to provide HEADs v3 in a human-readable format. For example, Client APIs.
-
-    {
-        "api_outgoing_conf": Number,
-        "api_incoming_conf": Number,
-        "free_mirror_rooms": Number,
-        "low_priority_rooms": Number,
-        "node_id": Number,
-        "algorithm": String(name of pubkey/sig algorithm)
-        "pubkey": String(pubkey.pubkey_content in base58),
-        "blockstamp": String(BlockId-BlockHash in base16),
-        "software_name": String,
-        "software_version": String,
-        "signature": String(signature.sig_content in base64),
-        "step", Number,
-    }
-
 #### api_outgoing_conf interpretation
 
 | bit       | signification             |
@@ -811,6 +882,91 @@ There are still 4 flags for future network layers that could be implemented in t
 
 There are still 5 flags for future network layers that could be implemented in the future.
 
+#### HEAD v3 Raw format
+
+Approximate description :
+
+    VERSION:CURRENCY:OUTGOING_CONF:INCOMING_CONF:FREE_MIRROR_ROOMS:FREE_MEMBER_ROOMS:NODE_ID:PUBLIC_KEY:BLOCKSTAMP:SOFTWARE:SOFT_VERSION
+    SIGNATURE
+    STEP
+
+_/!\ This description is approximate, it allows you to quickly understand the format but is not authoritative for developing a code to parse the format exactly. If you want to develop a code using this format, please refer to its PEG grammar._
+
+Example :
+
+    3:g1:0:0:0:0:0:7iMV3b6j2hSj5WtrfchfvxivS9swN3opDgxudeHq64fb:50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370:durs:0.1.0-a0.1
+    vwlxpkCbv83qYSiClYA/GD35hs0AsZBnqv7uoE8hqlarT2c6jVRKhjp8JBqmRI7Se4IDwC2owk0mF4CglvyACQ==
+    2
+
+HEAD v3 PEG grammar :
+
+    ```
+    // Single character rules
+    nl = _{ "\n" }
+    no_zero_hexa_lower = @{ '1'..'9' | 'a'..'f' }
+    hexa_lower = @{ ASCII_DIGIT | 'a'..'f' }
+    hexa_upper = @{ ASCII_DIGIT | 'A'..'F' }
+    base58 = { !("O" | "I" | "l") ~ ASCII_ALPHANUMERIC }
+    base64 = { ASCII_ALPHANUMERIC | "+" | "/" }
+
+    // Numbers rules
+    tens = @{ '1'..'9' ~ ASCII_DIGIT }
+    u8_hundreds = @{ ("2" ~ ('0'..'4' ~ ASCII_DIGIT | ('0'..'5'){2})) | ("1" ~ ASCII_DIGIT{2}) }
+    u8 = @{ u8_hundreds | tens | ASCII_DIGIT }
+    no_zero_u_int = @{ '1'..'9' ~ ASCII_DIGIT* }
+    u_int = @{ "0" | no_zero_u_int }
+
+    // Usefull types rules
+    currency = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "-" | "_"){,255} }
+    block_id = @{ u_int }
+    hash = @{ hexa_upper{64} }
+    pubkey = @{ base58{43,44} }
+    blockstamp =  ${ block_id ~ "-" ~ hash }
+    ed25519_sig = @{ base64{88} | (base64{87} ~ "=") | (base64{86} ~ "==") }
+
+    // HEADv3 rules
+    api_outgoing_conf = @{ u8 }
+    api_incoming_conf = @{ u8 }
+    free_member_rooms = @{ u8 }
+    free_mirror_rooms = @{ u8 }
+    software = @{ ASCII_ALPHA ~ ASCII_ALPHANUMERIC* }
+    soft_version = @{ ASCII_DIGIT ~ "." ~ ASCII_DIGIT ~ "." ~ ASCII_DIGIT ~ ("-" ~ ("a" | "b" | "rc") ~ ASCII_DIGIT ~ ("." ~ ASCII_DIGIT){0,2})? }
+    step = @{ u_int }
+
+    head_v3 = ${
+        "3:" ~ currency ~ ":" ~
+        api_outgoing_conf ~ ":" ~
+        api_incoming_conf ~ ":" ~
+        free_member_rooms ~ ":" ~
+        free_mirror_rooms ~ ":" ~
+        node_id ~ ":" ~
+        pubkey ~ ":" ~
+        blockstamp ~ ":" ~
+        software ~ ":" ~
+        soft_version ~ nl ~
+        ed25519_sig? ~
+        (nl ~ step)?
+    }
+    ```
+
+#### HEADv3 JSON format
+
+This human-readable format will be used by all APIs that wish to provide heads in a human-readable format. For example, Client APIs.
+
+    {
+        "content": String(VERSION:CURRENCY:OUTGOING_CONF:INCOMING_CONF:FREE_MIRROR_ROOMS:FREE_MEMBER_ROOMS:NODE_ID:PUBLIC_KEY:BLOCKSTAMP:SOFTWARE:SOFT_VERSION),
+        "signature": String(SIGNATURE in base64),
+        "step": Number
+    }
+
+Example :
+
+    {
+        "content": "3:g1:0:0:0:0:0:7iMV3b6j2hSj5WtrfchfvxivS9swN3opDgxudeHq64fb:50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370:durs:0.1.0-a0.1",
+        "signature": "vwlxpkCbv83qYSiClYA/GD35hs0AsZBnqv7uoE8hqlarT2c6jVRKhjp8JBqmRI7Se4IDwC2owk0mF4CglvyACQ==",
+        "step": 2,
+    }
+
 ### Documents messages
 
 All WS2Pv2 documents are necessarily in Binary Format. When document binarization is coded in Duniter-ts, then it will be necessary to define a common binary format for each document. For performance reasons, we will probably opt for the format in which each document is signed.
-- 
GitLab