From ca16cfd1645b718e2bcb62d34126886ce0373d91 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Tue, 5 May 2020 07:42:04 -0500 Subject: [PATCH] Mostly finish message format document. --- dev_docs.md | 31 ++ FAQ.md => faq.md | 0 glossary_terms.md | 913 ------------------------------- lipmaa.png | Bin 0 -> 41257 bytes lipmaa.svg | 2 - DEV_DOCS.md => message_format.md | 138 +++-- ROADMAP.md => roadmap.md | 0 7 files changed, 116 insertions(+), 968 deletions(-) create mode 100644 dev_docs.md rename FAQ.md => faq.md (100%) delete mode 100644 glossary_terms.md create mode 100644 lipmaa.png delete mode 100644 lipmaa.svg rename DEV_DOCS.md => message_format.md (55%) rename ROADMAP.md => roadmap.md (100%) diff --git a/dev_docs.md b/dev_docs.md new file mode 100644 index 0000000..0a57ea4 --- /dev/null +++ b/dev_docs.md @@ -0,0 +1,31 @@ +# Messages: The Basic Building Block + +The most important protocol concept is that of the "message". +In their most simple form, Pigeon protocol messages are just ASCII text documents. They are human readable and can even be created by hand in a text editor, though most clients will provide better means of authoring messages. + +Below is an example of such a message: + +``` +author @MF312A76JV8S1XWCHV1XR6ANRDMPAT2G5K8PZTGKWV354PR82CD0.ed25519 +kind weather_report +prev %ZV85NQS8B1BWQN7YAME1GB0G6XS2AVN610RQTME507DN5ASP2S6G.sha256 +depth 3 +lipmaa 2 + +temperature:"22.0C" +webcam_photo:&FV0FJ0YZADY7C5JTTFYPKDBHTZJ5JVVP5TCKP0605WWXYJG4VMRG.sha256 +weather_reported_by:@0DC253VW8RP4KGTZP8K5G2TAPMDRNA6RX1VHCWX1S8VJ67A213FM.ed25519 + +signature JSPJJQJRVBVGV52K2058AR2KFQCWSZ8M8W6Q6PB93R2T3SJ031AYX1X74KCW06HHVQ9Y6NDATGE6NH3W59QY35M58YDQC5WEA1ASW08.sig.ed25519 +``` + +The specifics of the message format are explained line-by-line [in the message format explanation document](message_format.md). +Please read this document before continuing. + +# Bundles: The Transmission Medium + +WORK IN PROGRESS. + +# Up Next + +This concludes the developer documentation. Please email us with questions. To learn more, continue to the [idea bin](IDEAS.md). diff --git a/FAQ.md b/faq.md similarity index 100% rename from FAQ.md rename to faq.md diff --git a/glossary_terms.md b/glossary_terms.md deleted file mode 100644 index eeb9f7e..0000000 --- a/glossary_terms.md +++ /dev/null @@ -1,913 +0,0 @@ -001 ability -001 able -001 about -001 above -001 acceptable -001 across -001 actual -001 actually -001 add -001 added -001 aebrpezjfzwba -001 agnostic -001 aj -001 allocation -001 along -001 alternative -001 amalgam -001 analog -001 ancient -001 anrdmpat -001 anyone -001 append -001 applied -001 apply -001 appreciated -001 approach -001 apps -001 april -001 ar -001 arrays -001 art -001 ascii -001 ask -001 asp -001 assist -001 asw -001 auditing -001 authoring -001 authorities -001 automatically -001 avn -001 avoid -001 ayx -001 ba -001 backup -001 backups -001 backwards -001 baggage -001 bare -001 bc -001 bc- -001 beginning -001 being -001 best -001 bew -001 beyond -001 big -001 blobs -001 block -001 blogging -001 bluetooth -001 bnf -001 board -001 body -001 both -001 boxer -001 brainstorming -001 break -001 browser -001 bug -001 bundle-consuming -001 but -001 bwqn -001 ca -001 cards -001 cause -001 cd -001 censorship -001 changed -001 changes -001 civilizations -001 code -001 common -001 compactness -001 compatibility -001 completed -001 complicated -001 compression -001 compromise -001 compromises -001 computer -001 computers -001 conditions -001 config -001 configurability -001 connection -001 consider -001 consortium -001 constrained -001 constraints -001 contain -001 containing -001 content -001 contents -001 continued -001 contrast -001 control -001 convention -001 cool -001 core -001 could -001 cpu -001 crap -001 create -001 crypto -001 cryptography -001 da -001 dae -001 dashes -001 data-integrity -001 database -001 date -001 db -001 dc -001 decentralized -001 decoupling -001 delay-tolerant -001 dependencies -001 designed -001 deterministic -001 diagram -001 difference -001 different -001 differentiation -001 difficult -001 direct -001 discovery -001 diversity -001 dn -001 dns -001 docs -001 documents -001 does -001 don't -001 dots -001 down -001 downloading -001 ds -001 due -001 early -001 easy -001 easy-to-implement -001 ecosystem -001 edge -001 editor -001 editors -001 efficient -001 efforts -001 embeddable -001 enable -001 encoding -001 end -001 enough -001 ensure -001 enthusiast -001 entirely -001 eternity -001 ever -001 evil -001 examples -001 excellent -001 exchange -001 exchanged -001 exists -001 explore -001 export -001 external -001 ez -001 f- -001 fag -001 famous -001 favor -001 feeds -001 filesystem -001 finalize -001 finalized -001 find -001 finish -001 finished- -001 fixes -001 fj -001 flavored -001 fm -001 follow -001 forged -001 form -001 formal -001 forth -001 framed -001 free -001 fun -001 functioning -001 fv -001 gained -001 game -001 games -001 gateway -001 gateways -001 gauntlet -001 gb -001 gitbook -001 glossary -001 goes -001 grammar -001 grant -001 grid -001 ground -001 guarantee -001 gui -001 guide -001 halting -001 happy -001 hash -001 having -001 header -001 hello -001 helped -001 hgy -001 hhvq -001 hierarchy -001 higher-level -001 hooks -001 hopefully -001 however -001 http -001 hurt -001 i-iii -001 i'm -001 i've -001 ignored -001 ii -001 iii -001 implementation-specific -001 import -001 important -001 improvements -001 incorporate -001 indentation -001 initial -001 innovative -001 integrity -001 interest -001 intermittent -001 internal -001 its -001 iv -001 jqg -001 jspjjqjrvbvgv -001 jssfbaz -001 jttfypkdbhtzj -001 jv -001 jvvp -001 kcw -001 kdfyax -001 kf -001 kfqcwsz -001 kgtzp -001 khmdzzzrwk -001 knowledge -001 known -001 kys -001 lack -001 language -001 larger -001 latency -001 later -001 layer -001 let's -001 level -001 lexer -001 likely -001 limit -001 link -001 links -001 listening -001 local -001 locally -001 lock -001 logger -001 logging -001 look -001 mail -001 main -001 maintenance -001 major -001 makes -001 making -001 mapping -001 maritime -001 maturity -001 mechanisms -001 mention -001 mentioned -001 mesh -001 messenger -001 metal -001 mf -001 microblogging -001 mike -001 minimalism -001 minimize -001 mjsstchyp -001 model -001 monolithic -001 much -001 mule -001 multiple -001 must -001 my -001 names -001 namespacing -001 natural -001 ndatge -001 needed -001 neighboring -001 nested -001 networks -001 never -001 newsgroup -001 nh -001 nice-to-haves -001 nntp -001 node -001 nodejs -001 non-goals -001 nor -001 npwz -001 nqs -001 number -001 off -001 off-grid -001 offer -001 offers -001 offline-first -001 offline-only -001 offloaded -001 ok -001 old -001 online -001 operation -001 opinion -001 opposed -001 option -001 options -001 outreach -001 outstanding -001 own -001 package -001 packaged -001 pages -001 pair -001 pairs -001 parse -001 parsed -001 partial -001 parties -001 pb -001 pcta -001 peer -001 peer's -001 peers-of-peers -001 performance -001 performantly -001 persistence -001 phases -001 philosophy -001 photo -001 pieces -001 pigeons -001 platform -001 plugins -001 point -001 point-of-interest -001 poor -001 portable -001 ported -001 postal -001 power -001 powered -001 pr -001 practice -001 prefer -001 prevent -001 prior -001 product -001 production -001 production-grade -001 proliferate -001 promote -001 promotes -001 proof -001 proof-of-concept -001 prototype -001 prtocol -001 pseudonymity -001 pseudonyms -001 published -001 pubs -001 pztgkwv -001 qdfnsaf -001 qy -001 racing -001 ram -001 read -001 readers -001 ready -001 reasons -001 reboot -001 recent -001 recipient -001 redundant -001 redundantly -001 reference -001 referenced -001 regain -001 regardless -001 remote -001 rename -001 replicate -001 reply -001 report -001 reported -001 require -001 research -001 resistance -001 resource -001 rh -001 role -001 root -001 rp -001 rqtme -001 rsf -001 running -001 rust -001 rx -001 safe -001 say -001 schemas -001 scheme -001 sd -001 secret -001 section -001 seen -001 sense -001 sensor -001 serial -001 seriously -001 serves -001 services -001 sessions -001 set -001 set- -001 should -001 showing -001 shown -001 shutdown -001 similar -001 simpler -001 simplified -001 simulated -001 since -001 singletons -001 site -001 sj -001 slow -001 small -001 smaller -001 sneakernet-only -001 software -001 solar -001 solicited -001 soliciting -001 some -001 something -001 ssh -001 stability -001 stabilize -001 standard -001 starts -001 startup -001 status-quo -001 store -001 store-and-forward -001 structure -001 suitable -001 summary -001 super -001 sync -001 synchronization -001 synchronizing -001 system -001 takes -001 tamper-resistant -001 tampering -001 tapmdrna -001 targets -001 tckp -001 temperature -001 temporarily -001 term -001 terms -001 tf -001 thanks -001 them -001 themselves -001 then -001 these -001 throughput -001 tied -001 tool -001 tpm -001 tradeoffs -001 transfer -001 transmission -001 transport -001 trying -001 turn-based -001 tyson -001 unless -001 until -001 update -001 uptime -001 url -001 used -001 utilize -001 validate -001 vaporsoft -001 verify -001 version -001 vhcwx -001 viable -001 vj -001 vmrg -001 vtj -001 vvgrz -001 wa -001 wanted -001 watching -001 way -001 ways -001 wea -001 webcam -001 were -001 what's -001 where -001 whitespace -001 who -001 windows -001 wip -001 within -001 writing -001 ws -001 wwxyjg -001 wyr -001 xr -001 xs -001 xwchv -001 xyz -001 yame -001 ydqc -001 years -001 ym -001 ymr -001 yqbeg -001 yzady -001 zv -002 addressed -002 after -002 akkgw -002 also -002 altered -002 anonymity -002 app -002 areas -002 ascii-based -002 asked -002 authored -002 available -002 back -002 backed -002 bamboo -002 become -002 benefits -002 between -002 bin -002 borrows -002 bundle -002 bundles -002 cannot -002 cli -002 conceptual -002 concerns -002 concludes -002 contact -002 crockford -002 current -002 custom -002 cx -002 delay -002 development -002 devices -002 differs -002 draft -002 dx -002 each -002 easier -002 efcj -002 eg -002 encrypted -002 encryption -002 even -002 every -002 except -002 existing -002 fat -002 feature -002 feedback -002 few -002 footer -002 found -002 frequently -002 friend -002 get -002 gmv -002 goal -002 gw -002 hand -002 handbook -002 handled -002 hc -002 heabfd -002 high -002 human -002 idea -002 identities -002 if -002 instead -002 intended -002 internet -002 iot -002 it's -002 json -002 just -002 kdkk -002 ktngsdbkmsa -002 languages -002 learn -002 legacy -002 less -002 libraries -002 libs -002 limited -002 long -002 low -002 made -002 maintain -002 malicious -002 means -002 message's -002 messaging -002 might -002 mostly -002 nesting -002 new -002 nodes -002 numerous -002 once -002 other -002 out -002 overhead -002 party -002 people -002 plentiful -002 points -002 possibly -002 privacy -002 production-scale -002 re-write -002 readable -002 referencing -002 reliance -002 replicated -002 resistant -002 roadmap -002 ruby -002 sent -002 series -002 servers -002 signed -002 signing -002 snde -002 spec -002 sqlite -002 string -002 suited -002 tamper -002 te -002 text -002 tgfds -002 things -002 third -002 three -002 tolerant -002 too -002 traditional -002 transmitted -002 two -002 unlike -002 verification -002 vw -002 wasm -002 we've -002 weather -002 well -002 what -002 wish -002 without -002 wkg -002 world -002 would -002 your -003 always -003 any -003 assume -003 base -003 below -003 better -003 blob -003 carriage -003 case -003 concept -003 connectivity -003 created -003 currently -003 design -003 developer -003 easily -003 email -003 empty -003 entry -003 feed -003 files -003 here -003 ideas -003 identity -003 implementations -003 information -003 inspired -003 involved -003 list -003 logs -003 make -003 may -003 medium -003 need -003 only -003 over -003 overview -003 platforms -003 please -003 portability -003 project -003 protocols -003 rather -003 return -003 see -003 serve -003 sig -003 simple -003 social -003 storage -003 swarm -003 tcp -003 their -003 theoretically -003 though -003 time -003 udp -003 value -003 was -003 work -004 although -004 build -004 clients -004 configuration -004 considered -004 continue -004 depth -004 developers -004 etc -004 features -004 first -004 focus -004 format -004 gossip -004 into -004 least -004 like -004 log -004 most -004 network -004 networking -004 next -004 none -004 one -004 prev -004 problems -004 provide -004 questions -004 real-world -004 serialization -004 sha -004 sharing -004 so -004 ssb -004 they -004 us -004 which -004 working -005 allow -005 been -005 built -005 do -005 embedded -005 file -005 help -005 how -005 i -005 implementation -005 key -005 library -005 many -005 more -005 peer-to-peer -005 specification -005 start -005 up -005 uses -006 at -006 author -006 data -006 documentation -006 example -006 has -006 have -006 kind -006 lines -006 lipmaa -006 on -006 scuttlebutt -006 secure -006 signature -006 using -006 when -006 written -006 you -007 application -007 complete -007 ed -007 possible -007 such -007 via -008 all -008 cases -008 line -008 than -008 there -009 sneakernet -009 systems -010 from -010 with -011 an -011 applications -011 as -011 peers -011 support -012 it -012 we -013 can -014 not -014 or -015 message -015 messages -015 use -016 no -017 client -018 phase -018 will -023 by -024 are -024 for -024 that -025 this -027 in -028 pigeon -028 protocol -029 be -041 and -048 is -050 of -055 to -072 the -078 a \ No newline at end of file diff --git a/lipmaa.png b/lipmaa.png new file mode 100644 index 0000000000000000000000000000000000000000..be6a655901cf0e65b52e1d85a19c50a1ead6effd GIT binary patch literal 41257 zcmYgY1z1$e+s8mk>6UOoVQJ|GSxS0AI;Bf#>5>+tL8QA=DQPL`?(ULaa)DjGgV%e% zzYh<)=P+mHjo+Iy$4^j2=_i=vm?$VHPh?(8sGy)c`T=}jMZXXHPCAA{fR6``5E)f; zbo99urDYV9XDBifVydnwdkZd}Z_bci$A>-d24!46eo?G>EE(M-_UcQ4?;gWg_*xOz z&yRpeS>hqteZM`HXC64pug>uWG6N4bQ~DhT5o>Ycug7>S$9Uc^4T&DGrKF^!iS)Bs z>cdkU3#@y1?$-b3Uwm>_iOatiC@8&D5YT^D&j|m2-2dFh4Y;HGpMTHL1ONSs@(LI8 z-oF>V|MP5|biNX0F?Ct#)1u#tHHO~1H+ApZ`?9ZUZ1KmyNtPooo!%ZghiwgTkcBI1 z>z=>(_WmrNzW~ zcL6zeAG`gnSAB;-K%d_!TQTJ98GAUxO|L=_2zo$*F+yW$O|nZrNz^+L2)6= z$V&Lib*xtOW-mGY3jqY#;Oy2}enLSN2>pLDY@RPErko%21w^^zdlQlBcJ2sRt25IC zSa^9Zre4Lj>j_^s9!ZR;2Slm$5%bOe@1r6iS(gXa+21)h>zxic-)?`sQJ-tM#(})< z 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

)Rx0)~CXZ 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 -
1
1
2
2
3
3
5
5
4
4
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
18
18
17
17
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
31
31
30
30
32
32
33
33
34
34
35
35
36
36
37
37
38
38
39
39
40
40
\ No newline at end of file diff --git a/DEV_DOCS.md b/message_format.md similarity index 55% rename from DEV_DOCS.md rename to message_format.md index 212deef..6ea0fbc 100644 --- a/DEV_DOCS.md +++ b/message_format.md @@ -1,9 +1,8 @@ -# It Starts With a Message... +# Exploring the Pigeon Message Format -The most important protocol concept is that of the "message". -In their most simple form, Pigeon protocol messages are just ASCII text documents. They are human readable and can even be created by hand in a text editor, though most clients will provide better means of authoring messages. +In the test that follows, we will explore a pigeon message line-by-line. -Below is an example of such a message: +The example message is shown in its entirety below: ``` author @MF312A76JV8S1XWCHV1XR6ANRDMPAT2G5K8PZTGKWV354PR82CD0.ed25519 @@ -19,9 +18,7 @@ weather_reported_by:@0DC253VW8RP4KGTZP8K5G2TAPMDRNA6RX1VHCWX1S8VJ67A213FM.ed2551 signature JSPJJQJRVBVGV52K2058AR2KFQCWSZ8M8W6Q6PB93R2T3SJ031AYX1X74KCW06HHVQ9Y6NDATGE6NH3W59QY35M58YDQC5WEA1ASW08.sig.ed25519 ``` -Let's explore each line of a message. - -### Line 1: `author` +### Line 1: `Author` EXAMPLE: @@ -39,7 +36,7 @@ The steps to generate a valid identity are: 2. Add an `@` symbol to the beginning of the string from step 1. 3. Add a `.ed25519` string to the end of the string from step 2. -### Line 2: `kind` +### Line 2: `Kind` EXAMPLE: @@ -59,7 +56,7 @@ It must meet the following criteria: * underscores (`_`) * Symbols used for multihashes, such as `@`, `&` and `%` (covered later). -### Line 3: `prev` +### Line 3: `Prev` EXAMPLE: @@ -81,7 +78,7 @@ Message multihashes are calculated as follows: 2. The next 52 characters are a [Crockford base 32](https://www.crockford.com/base32.html) SHA512 hash of the previous message's content. 3. The message multihash ends in `.sha512`. -### Line 4: `depth` +### Line 4: `Depth` EXAMPLE: @@ -93,21 +90,15 @@ Pigeon messages exist in a linear sequence which only moves forward and never "f Every message has a `depth` field to indicate its "place in line". Because every message has an ever-increasing integer that never duplicates, every message in a Pigeon feed will have a unique hash. This is true even if messages have identical body content. -### Line 5: `lipmaa` +### Line 5: `Lipmaa` **THIS FIELD WAS WRITTEN INCORRECTLY. THIS WILL CHANGE SOON. YOU CAN SAFELY MOVE TO THE NEXT SECTION OF THE DOCS** This concept was borrowed from the [Bamboo protocol](https://github.com/AljoschaMeyer/bamboo#links-and-entry-verification) and [Helger Lipmaa's thesis](https://kodu.ut.ee/~lipmaa/papers/thesis/thesis.pdf). -EXAMPLE: +The `lipmaa` field (often called a "Lipmaa Link") is a special kind of `prev` field that allows partial verification of feeds. This field makes it possible to verify a single message (or subset of messages) without downloading the entire chain of messages. -``` -lipmaa 2 -``` - -The `lipmaa` field (often called a "Lipmaa Link") is a special kind of `depth` field that allows partial verification of feeds. This field makes it possible to verify a single message (or subset of messages) without downloading the entire chain of messages. - -![](lipmaa.svg) +![](lipmaa.png) The `lipmaa` field is calculated as follows: @@ -140,41 +131,82 @@ def lipmaa(n) end ``` -### Line 6: Empty carriage return (body start) -### Lines 7: Entry containing a string -### Lines 8: Entry referencing a blob -### Lines 9: Entry referencing a peer's identity -### Lines 10: Empty Carriage Return (footer start) +### Line 6: Body Start (Empty Line) + +Once all headers are added, a client must place an empty line (`\n`) after the header. +The empty line signifies the start of the message body. + +Some notes about body entries: + + * The body of a message starts and ends with an empty line (`\n`). + * Every body entry is a key value pair. Keys and values are separated by a `:` character (no spaces). + * A key must be 1-90 characters in length + * A key cannot contain whitespace or control characters + * A key may contain any of the following characters: + * alphanumeric characters (a-z, A-Z, 0-9) + * dashes (`-`) + * underscores (`_`) + * Symbols used for multihashes, such as `@`, `&` and `%` (covered later). + * A value may be a: + * A string (128 characters or less) + * A multihash referencing an identity (`@`), a message (`%`) or a blob (`&`). + +### Lines 7: Entry Containing a String + +EXAMPLE: + +``` +temperature:"22.0C" +``` + +Body entries are defined by user and contain key/value pairs of application-specific data. +When a key/value pair represents something other than an identity, blob or message ID, a string is used. +Strings can be used for any type of data that does not fit into the other three categories. +Strings must be less than or equal to 128 characters in length. +The example above is the most simple kind of body entry. It specifies an arbitrary string representing the current temperature. + +### Lines 8: Entry Referencing a Blob + +EXAMPLE: + +``` +webcam_photo:&FV0FJ0YZADY7C5JTTFYPKDBHTZJ5JVVP5TCKP0605WWXYJG4VMRG.sha256 +``` + +Applications may attach files to messages in the form of blobs. Blobs are referenced using a blob multihash. + + * Starts with a `&` character. + * Ends with `.sha256` + * Contains exactly 52 characters between the `&` and `.sha256` parts. This is a SHA256 hash of the blob's content, represented in Crockford Base 32 encoding. + +A blob is referenced in a message's key or value. A client will include a blob's content in a "bundle" (explained later). + +### Lines 9: Entry Referencing a Peer's Identity + +EXAMPLE: + +``` +weather_reported_by:@0DC253VW8RP4KGTZP8K5G2TAPMDRNA6RX1VHCWX1S8VJ67A213FM.ed25519 +``` + +A message may reference other identities (or its own identity) by using an identity sigil either in the key or value portion of the entry. +This is analogous to "social tagging" seen in many social networks. + +### Lines 10: Empty Carriage Return (Footer Start) + +The last part of a message is the footer. Like a message body, a message footer starts and ends with an empty line. +The footer is essential for ensuring the tamper resistant properties of a Pigeon message. + ### Lines 11: Signature Line -### Lines 12: Empty Carriage Return (message end) -# Sharing Messages and Blobs via Bundles -# Glossary of Terms -**This list is out of date.** Numerous changes and problems were addressed in the implementation of a client. We will update this list in May of 2020. +EXAMPLE: - * Header - * Blob - * Crockford Base32 - * NONE - * String - * Signature - * Value - * Message - * Blob Hash - * Key - * Pair - * Footer - * Bundle - * Kind - * Message Signature - * Feed - * Identity +``` +signature JSPJJQJRVBVGV52K2058AR2KFQCWSZ8M8W6Q6PB93R2T3SJ031AYX1X74KCW06HHVQ9Y6NDATGE6NH3W59QY35M58YDQC5WEA1ASW08.sig.ed25519 +``` - -# Running a CLI Client - -Pigeon currently has one CLI available. It is written in Ruby. Documentation can be found [here](https://tildegit.org/PigeonProtocolConsortium/pigeon_ruby) - -# Up Next - -This concludes the developer documentation. Please email us with questions. To learn more, continue to the [idea bin](IDEAS.md). +A signature starts with the word `signature` followed by a space. +After that, the body (including the trailing `\n`) is signed using the author's ED25519 key. +The signature is encoded with Crockford base 32. +The signature ends with `.sig.ed25519`. +An empty carraige return is added after the signature line. diff --git a/ROADMAP.md b/roadmap.md similarity index 100% rename from ROADMAP.md rename to roadmap.md