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