From dffa7a61006aa5c4050c954857aaf1357fe33242 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Tue, 1 Jun 2021 18:20:12 +0100 Subject: [PATCH] groups agent protocol (#142) * groups agent protocol * groups to chat protocol * update groups doc / diagram * group protocol commands * update group protocol * count messages for different group operations * broadcast and introduction as components for group protocol * list connections in the broadcast * protocol commands overview - using polymorphic commands * another version of group protocol based on "broadcast" and "introduction" concepts * update number of messages needed to establish connection * corrections to broadcast and introduction protocols * corrections in groups protocol * corrections --- rfcs/2021-03-18-groups.md | 25 ------ rfcs/2021-05-23-broadcast.md | 50 +++++++++++ rfcs/2021-05-23-groups2.md | 134 +++++++++++++++++++++++++++++ rfcs/2021-05-23-introduction.md | 41 +++++++++ rfcs/groups.mmd | 135 +++++++++++++++++++++++++++++ rfcs/intro.mmd | 42 +++++++++ rfcs/protocol_overview.md | 146 ++++++++++++++++++++++++++++++++ 7 files changed, 548 insertions(+), 25 deletions(-) delete mode 100644 rfcs/2021-03-18-groups.md create mode 100644 rfcs/2021-05-23-broadcast.md create mode 100644 rfcs/2021-05-23-groups2.md create mode 100644 rfcs/2021-05-23-introduction.md create mode 100644 rfcs/groups.mmd create mode 100644 rfcs/intro.mmd create mode 100644 rfcs/protocol_overview.md diff --git a/rfcs/2021-03-18-groups.md b/rfcs/2021-03-18-groups.md deleted file mode 100644 index 6da1fba69..000000000 --- a/rfcs/2021-03-18-groups.md +++ /dev/null @@ -1,25 +0,0 @@ -# SMP agent groups - -## Problems - -- device/user profile synchronisation -- chat group communication - -Both problems would require message broadcast between a group of SMP agents. - -## Solution: basic symmetric groups via SMP agent protocol - -Additional commands and message envelopes to SMP agent protocol to provide an abstraction layer for device synchronisation and chat groups. - -The groups are fully symmetric, all agent who are members of the group have equal rights and can join and leave group at any time. - -All the information about the groups is stored only in agents, the commands are used to synchronise the group state between the agents. - -```abnf -group_command = create_group / add_to_group / remove_from_group / leave_group -group_response = group_created / added_to_group / removed_from_group -group_notification = added_to_group_by / removed_from_group_by / left_group -create_group = %s"GNEW " group_name ; cAlias must be empty -add_to_group = %s"GADD " group_name ; cAlias is the connection to add to the group -added_to_group = %s"GADDED " name ; cAlias is the connection added to the group -``` \ No newline at end of file diff --git a/rfcs/2021-05-23-broadcast.md b/rfcs/2021-05-23-broadcast.md new file mode 100644 index 000000000..506118d02 --- /dev/null +++ b/rfcs/2021-05-23-broadcast.md @@ -0,0 +1,50 @@ +# SMP agent broadcast + +## Problem + +Support agent message broadcast to multiple connections. + +It is done in ad-hoc way as part of the previous [groups proposal](./2021-05-23-groups2.md) - this proposal defines broadcast as a separate agent primitive to simplify group management. + +It can also be used for other purposes when the same message needs to be sent to multiple recipients without creating groups. + +## Solution + +A minimal protocol of additional client commands to create, manage and use broadcasts. + +From the point of view of the recipient this will look like a normal message, as if the sending agent executed multiple send commands (in fact, broadcast can be implemented by agent sending itself multiple SEND commands) + +### Commands and messages + +- command `B:bId? NEW` - create broadcast (response is `B:bId OK`, or `ERR` if broadcast already exists) +- command `B:bId ADD C:cId` - add existing connection to a broadcast (response is `B:bId OK` or `ERR`, e.g. if connection already added or does not exist) +- command `B:bId SEND msg` - broadcast message (response is multiple `B:cId SENT [C:bId] msgId` or ERR, separately for each connection and then for the broadcast) +- message `B:bId SENT [C:bId] msgId` - notification that the message is sent to a specific or all recipients +- command `B:bId REM C:cId` - remove connection from broadcast (response is `B:bId OK` or `ERR`) +- message `B:bId EMPTY` - all connections were removed from the broadcast +- command `B:bId DEL` - delete broadcast (response is `B:bId OK` and when the last connection is removed an additional `B:bId EMPTY` is sent) +- command `B:bId LS` - list connections in broadcast, response is `B:Id MS space_separated_connections` +- message `B:bId MS space_separated_connections` + +## Questions + +1. Should broadcast IDs use the same namespace as connection IDs (and as group IDs)? Having the same namespace for all abstractions that the agent can operate on can be helpful, as it can also allow implementing some queries to determine which type a given ID has, but it also increases implementation complexity. + +2. Given that this abstraction would be used as internal abstraction for groups (same as connections internal to the group), it might be better to implement "agent users", each with its own connection namespace. In this case agent would use itself as one of the users. + +3. There is a similarity of commands for connections, groups and broadcasts, they only differ on the single-letter prefix. We could do one of the following: + - use the same command for different object types. This feels incorrect and error prone on its own. + - extend transmission structure with the field defining the object type (connection, group, broadcast, etc.). + +In this case, the transmission would look like: + +``` +agentTransmission = [corrId] CRLF objectType:[objectID] CRLF agentCommand +objectType = C | B | G ; this is the additional field +``` + +This approach would allow reusing the existing command avoiding the unnecessary repetition. + +In this case, the command type could be parameterized with the list of supported agent object types, so we can ensure on the type level that only allowed commands can be constructed. + +EDIT: This approach is already implemented diff --git a/rfcs/2021-05-23-groups2.md b/rfcs/2021-05-23-groups2.md new file mode 100644 index 000000000..672d807a1 --- /dev/null +++ b/rfcs/2021-05-23-groups2.md @@ -0,0 +1,134 @@ +# SMP agent groups + +## Problems + +- device/user profile synchronisation +- group communication + +Both use cases can be facilitated by message broadcasts between a group of SMP agents. + +## Solution: symmetric groups as part of SMP agent protocol + +The proposed approach does not scale to large groups, as each agent has to broadcast the messages of their clients to all other agents in the group. While for large group it is more effective to have a server managing the list of group members, it introduces the challenges with key distribution, privacy etc. + +This proposal contains the set of additional SMP agent commands and message envelopes to provide a low level abstraction for group communication. + +The groups are symmetric, all agents who are members of the group have equal rights and can add and remove members and leave group. Higher level protocol can manage the permissions of the different users, user and group profiles, using reserved fields for passing arbitrary information about the groups and the members. + +All the information about the groups is stored only in the agents. + +## Group message integrity + +Two approaches are possible: + +1. Each agent on a regular interval sends to all agents the sender IDs and the digests of the last messages from all agents they communicate with. +To avoid `(n-1)*n` messages for each group integrity verification, IDs and digests from all senders can be compacted in one messages: + +``` +broadcast: %s"CHECK" SP memId1 ":" msgId1 ":" hash1 ":" status1 SP memId2 ":" msgId2 ":" hash2 ":" status2 +``` + +A side question is that we currently do not support large agent messages; possibly we should support messages larger than SMP block size to simplify this and other scenarios, similarly to how websockets protocol does it. There might still be a limit to how large the full message can be. That probably requires re-thinking of how messages are managed and separation of message reception from the servers and message delivery to the clients, but this is likely to be required anyway for when we start running the agent in the background. + +There may be two situations to consider: + +1) The recipient of this verification message can have the same message as the last one or they can have more messages received - both such scenarios are ok and do not necessarily indicate a problem, as they just might be slightly ahead in receiving the messages. They would make the last matching message as ok, and the latter messages would remain unknown - it does not indicate the lack of integrity of the group, although if the next integrity check without the same messages does (this needs to be clarified). +2) The recipient of this verification message can have fewer messages received. This situation can be resolved in several ways: +- try to retrieve all messages from the queue that is behind. It might work, but it may be that the sender is simply trying to send messages because the network is down. +- wait until the next integrity check and only report integrity violation if during the next integrity check they still cannot reconcile the previous integrity check. This is probably an acceptable compromise. + +2. Each agent sends message receipts to sending agents - message receipts would contain a signature of the message hashes. In the agent uses the same verification key for each member of the group, as considered below, these receipts can be re-broadcasted to other agents (again, grouping them in one message to avoid `(n-1)*n` messages) as a proof that the messages were delivered. + +Comparing with the first approach, there are pros and cons: +- pros: + - the sender would only send such integrity check messages when they have send a message to all parties, thus avoiding the situation when some messages might have been not yet sent (or failed to send and they are retrying). +- cons: + - integrity check message mush contain a signature per member, so it would be substantially larger. + - agents must use the same verification key for all members in the group, complicating the group and connections management. + - in the same way as in the first scenario, some delivery notifications can be arbitrarily delayed. + +With either approach, each agent should probably track all the receipts of all messages from all agents. + +Overall the first approach seems better. It shows who received which messages and the only case where the lack of integrity would be reported if the message with the same order number is different or some messages are skipped to some recipients (i.e. they broadcast integrity violation for some of the senders). + +## Agent commands and messages syntax + +- command `G:gId? NEW` - create group (response is `G:gId OK`, or `ERR` if this group already exists) +- command `C:cId INTRO G:gId gInfo` - invite existing connection to a group +- message `C:cId REQ G:invID gInfo` - invitation to join the group +- command `G:gId? ACPT G:invId` - accept invitation (response is `G:gId OK`) +- message `G:gId CON C:cId` - 2 connections created with some group member (both for group and direct messages) +- message `G:gId MEM [C:cId]` - connection created with all group members for a given member or current client +- command `G:gId SEND msg` - send message to group +- message `G:gId SENT [C:cId] msgId` - notification that the message is sent and its internal ID +- message `G:gId MSG C:cId msgdata` - received group message from cId, msgdata is the same set of parameters as in `MSG` +- command `G:gId ACK msgId` - acknowledge message reception by the client +- message `G:gId RCVD [C:cId] msgId status` - message delivery notification +- command `G:gId LEAVE` - leave the group +- message `G:gId LEFT [C:cId]` - connection cId left the group +- command `G:gId REM C:cId` - remove group member (response is `G:gId OK`, followed by `REMD` notification) +- message `G:gId REMD C:cId [C:cId]` - member removed (who, by whom - if it's not the current user) +- message `G:gId OUT C:cId` - you are removed +- message `G:gId EMPTY` - all members left the group and it is now empty +- command `G:gId DEL` - delete the group (response is `G:gId OK`) +- message `G:gId DELD [C:cId]` - group deleted (by whom, if it's not the current user) +- command `G:bId LS` - list connections in the group, response is `MS space_separated_connections` +- message `G:bId MS space_separated_connections` + +## Agent message envelopes syntax (group-specific) + +- `GROUP C:mid G:inv gInfo` - invitation to join the group +- `MEM C:mid` - confirmation that member connected to all members +- `LEFT` - notification that member left the group +- `OUT` - you are removed from the group +- `REM C:mid` - remove member mid from the group +- `REMD C:mid` - confirmation that member is removed +- `DEL` - group is deleted +- `DELD` - confirmation that group is deleted + +## Protocol costs + +- Adding a member: + - GROUP - `1 + connection_cost` + - [introductions](./2021-05-23-introduction.md) - `(5 + 2 * connection_cost) * (n - 1)` + - MEM - `n - 1` + - total - `6n - 5 + (2n - 1) * connection_cost` agent messages, where connection cost is 5 messages (2 * HELLO, 2 * MSG - confirmation, 1 * REPLY ) agent messages, so the total is `16n - 10`. + +- Sending a message: + - MSG - (n-1) + - RCVD - (n-1) + - total - `2n-2` messages + +- Member leaves a group: + - LEFT - (n-1) + - total -`n-1` messages + +- Member is removed by another member: + - OUT - 1 + - REM - (n-1) + - REMD - (n-1) + - total `2n-1` messages + +- Group is deleted: + - DEL - (n-1) + - DELD - (n-1) + - total - `2n-2` messages + +- Group integrity verification: + - TODO + +## Questions + +1. Message verification keys. Agents use separate server and encryption key for each connection, but there can be a value of having the same message verification key used for all members in the group. E.g., a member can validate to other group members that the message was delivered to all group members by sending signed message receipts they receive from the agent (the second approach to group integrity verification above). This would mean that for each message `n*(n-1)` messages will be send, although signed receipts can be grouped to reduce this number. It can be done periodically, rather than on each message, as described [here](https://signal.org/blog/private-groups/). + +The [sequence digram for group operations](https://mermaid-js.github.io/mermaid-live-editor/#/view/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gIHBhcnRpY2lwYW50IE0gYXMgRXhpc3Rpbmc8YnI-bWVtYmVyIChNKVxuICBwYXJ0aWNpcGFudCBNQSBhcyBFeGlzdGluZzxicj5tZW1iZXI8YnI-YWdlbnQgKE1BKVxuICBwYXJ0aWNpcGFudCBBIGFzIEFsaWNlIChBKVxuICBwYXJ0aWNpcGFudCBBQSBhcyBBbGljZSdzPGJyPmFnZW50IChBQSlcbiAgcGFydGljaXBhbnQgQkEgYXMgQm9iJ3M8YnI-YWdlbnQgKEJBKVxuICBwYXJ0aWNpcGFudCBCIGFzIEJvYiAoQilcblxuICBub3RlIG92ZXIgQSwgQUE6IDEuIGNyZWF0ZSBuZXcgZ3JvdXAgKG5vIG1lbWJlcnMpXG4gIEEgLT4-IEFBOiBHOmdpZEE_IE5FVzxicj4oZ2lkQSAtIGdyb3VwIElEIG9mIHRoaXMgZ3JvdXAgZm9yIEEsPGJyPmNhbiBiZSBnZW5lcmF0ZWQgYnkgdGhlIGFnZW50KVxuXG4gIG5vdGUgb3ZlciBBQTogY3JlYXRlIFwiaW50ZXJuYWxcIiBicm9hZGNhc3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBncm91cDxicj4oQjogTkVXKVxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgT0tcblxuICBub3RlIG92ZXIgQSwgQkE6IDIuIGFkZCBCb2IgdG8gZ3JvdXBcblxuICBBIC0-PiBBQTogQzppZEFCIElOVFJPIEc6Z2lkQSBnSW5mbzxicj4oaWRBQiAtIGNvbm4gYWxpYXMgQSBoYXMgZm9yIEIpXG4gIFxuICBub3RlIG92ZXIgQUE6IGdlbmVyYXRlIG5ldyByYW5kb20gSUQgZm9yIG1lbWJlciBCIChtaWRCLCB1bmlxdWUgcGVyIGdyb3VwKTxicj5pbml0aWF0ZSBcImludGVybmFsXCIgY29ubmVjdGlvbiBnaWRBQiBmb3IgQiBpbiBncm91cDxicj4oaW50ZXJuYWwgbWVhbnMgdGhhdCBpdCBpcyBub3QgdmlzaWJsZSB0byB0aGUgY2xpZW50czxicj5hbmQgY2Fubm90IGJlIHVzZWQgd2l0aCBjbGllbnQgY29tbWFuZHMpXG5cbiAgQUEgLT4-IEJBOiB2aWEgaWRBQjogR1JPVVAgQzptaWRCIGc6Z0ludkFCIGdJbmZvXG4gIEJBIC0-PiBCOiBDOmlkQkEgUkVRIEc6aW52SUQgZ0luZm88YnI-KGludklEIC0gdG8gcmVmZXIgdG8gaXQgaW4gQUNQVClcbiAgQiAtPj4gQkE6IEc6Z2lkQj8gQUNQVCBHOmludklEPGJyPihSSkNUIEc6aW52SUQgY291bGQgYmUgYWRkZWQpXG5cbiAgbm90ZSBvdmVyIEJBOiBjcmVhdGUgZ3JvdXAgYW5kIFwiaW50ZXJuYWxcIiBicm9hZGNhc3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBncm91cDxicj4oQjogTkVXKVxuXG4gIEJBIC0-PiBCOiBHOmdpZEIgT0tcblxuICBCQSAtPj4gQUE6IGVzdGFibGlzaCBpbnRlcm5hbCBjb25uZWN0aW9uIGdpZEJBICh1c2luZyBnOmdJbnZBQikgZm9yIEEgaW4gZ3JvdXBcblxuICBub3RlIG92ZXIgQkEsIEFBOiBhZGQgY29ubmVjdGlvbnMgZ2lkQkEgYW5kIGdpZEFCIHRvIGJyb2FkY2FzdHM8YnI-KEI6IEFERClcbiBcbiAgQUEgLT4-IEE6IEc6Z2lkQSBDT04gQzppZEFCXG4gIEJBIC0-PiBCOiBHOmdpZEEgQ09OIEM6aWRCQVxuXG4gIG5vdGUgb3ZlciBNLCBCOiBGb3IgZWFjaCBleGlzdGluZyBtZW1iZXIgTTo8YnI-Y3JlYXRlIGFuZCBhY2NlcHQgaW50ZXJuYWwgaW50cm9kdWN0aW9uIGJldHdlZW4gY29ubmVjdGlvbnMsIHJlbGF0ZWQgdG8gdGhlIGdyb3VwLCB2aWEgZ2lkQUIvQkEvQU0vTUEsIGNvbm5lY3Rpb25zIGNyZWF0ZWQgYXJlIGdpZEJNIGFuZCBnaWRNQjxicj5UaGUgZmFjdCB0aGF0IHRoZSBpbnRyb2R1Y3Rpb24gYXJyaXZlcyB2aWEgY29ubmVjdGlvbiBhbGxvY2F0ZWQgZm9yIHRoZSBncm91cCwgYWxsb3dzIGFnZW50cyBpZGVudGlmeSBpdCBhcyBhIG5ldyBncm91cCBtZW1iZXIsIElEIHVzZWQgaW4gaW50cm9kdWN0aW9ucyBpcyBncm91cC1zY29wZWQgbWVtYmVyIElELlxuXG4gIG5vdGUgb3ZlciBBLCBCQTogb25jZSBhbGwgbWVtYmVycyB3ZXJlIHNlbnQgdG8gQlxuICBBQSAtPj4gQkE6IHZpYSBnaWRBQjogTUVNIEM6bWlkQlxuXG4gIG5vdGUgb3ZlciBCQSwgQjogb25jZSBhbGwgbWVtYmVycyBhcmUgY29ubmVjdGVkXG4gIEJBIC0-PiBCOiBHOmdpZEIgTUVNXG5cbiAgbm90ZSBvdmVyIEEsIEFBOiBvbmNlIGFsbCBtZW1iZXJzIHJlcG9ydGVkIGNvbm5lY3Rpb25cbiAgQUEgLT4-IEE6IEc6Z2lkQSBNRU0gQzppZEFCXG5cbiAgbm90ZSBvdmVyIE0sIEFBOiBmb3IgZWFjaCBtZW1iZXIgTVxuXG4gIEFBIC0-PiBNQTogdmlhIGdpZEFNOiBNRU0gQzptaWRCXG4gIE1BIC0-PiBNOiBHOmdpZE0gTUVNIEM6aWRNQlxuICBcbiAgbm90ZSBvdmVyIE0sIEI6IDMuIEIgc2VuZHMgbWVzc2FnZSB0byB0aGUgZ3JvdXBcblxuICBCIC0-PiBCQTogRzpnaWRCIFNFTkQgbXNnXG5cbiAgbm90ZSBvdmVyIEJBOiBzZW5kIG1lc3NhZ2UgdmlhIGFzc29jaWF0ZWQgYnJvYWRjYXN0IGFuZCByZXNwb25kIHRvIGNsaWVudCB3aXRoIFNFTlQgbm90aWZpY2F0aW9uc1xuXG4gIEJBIC0-PiBCOiBHOmdpZEIgU0VOVCBDOmlkQkEgaW50TXNnSURcbiAgQkEgLT4-IEI6IEc6Z2lkQiBTRU5UIEM6aWRCTSBpbnRNc2dJRFxuICBcbiAgbm90ZSBvdmVyIEJBLCBCOiBvbmNlIHNlbnQgdG8gYWxsXG4gIEJBIC0-PiBCOiBHOmdpZEIgU0VOVCBpbnRNc2dJRFxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgTVNHIEM6aWRBQiBpbnRNc2dJRCBtc2dkYXRhXG4gIEEgLT4-IEFBOiBHOmdpZEEgQUNLIGludE1zZ0lEXG4gIEFBIC0-PiBCQTogdmlhIGdpZEFCOiBSQ1ZEIGV4dE1zZ0lEIGhhc2ggc2lnXG4gIEJBIC0-PiBCOiBHOmdpZEEgUkNWRCBDOmlkQkEgaW50TXNnSUQgc3RhdHVzPGJyPihzdGF0dXMgLSBtZXNzYWdlIGludGVncml0eSBjaGVjaylcblxuICBNQSAtPj4gTTogRzpnaWRNIE1TRyBDOmlkTUIgaW50TXNnSUQgbXNnZGF0YVxuICBNIC0-PiBNQTogRzpnaWRNIEFDSyBpbnRNc2dJRFxuICBNQSAtPj4gQkE6IHZpYSBnaWRNQjogUkNWRCBleHRNc2dJRCBoYXNoIHNpZ1xuICBCQSAtPj4gQjogRzpnaWRNIFJDVkQgQzppZEJNIGludE1zZ0lEIHN0YXR1c1xuXG4gIG5vdGUgb3ZlciBCQSwgQjogb25jZSByZWNlaXZlZCBieSBhbGxcbiAgQkEgLT4-IEI6IEc6Z2lkTSBSQ1ZEIGludE1zZ0lEIHN0YXR1c1xuXG4gIG5vdGUgb3ZlciBNLCBCOiA0YS4gQSBsZWF2ZXMgZ3JvdXBcblxuICBBIC0-PiBBQTogRzpnaWRBIExFQVZFXG4gIEFBIC0-PiBBOiBHOmdpZEEgT0tcbiAgQUEgLT4-IEJBOiB2aWEgZ2lkQUI6IExFRlRcbiAgbm90ZSBvdmVyIEFBOiByZW1vdmUgZ2lkQUIsIHJlbW92ZSBmcm9tIGJyb2FkY2FzdFxuICBub3RlIG92ZXIgQkE6IHJlbW92ZSBnaWRCQSwgcmVtb3ZlIGZyb20gYnJvYWRjYXN0XG4gIEJBIC0-PiBCOiBHOmdpZEIgTEVGVCBDOmlkQkFcblxuICBBQSAtPj4gTUE6IHZpYSBnaWRBTTogTEVGVFxuICBub3RlIG92ZXIgQUE6IHJlbW92ZSBnaWRBTSwgcmVtb3ZlIGZyb20gYnJvYWRjYXN0XG4gIG5vdGUgb3ZlciBNQTogcmVtb3ZlIGdpZE1BLCByZW1vdmUgZnJvbSBicm9hZGNhc3RcbiAgTUEgLT4-IE06IEc6Z2lkTSBMRUZUIEM6aWRNQVxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgTEVGVFxuXG4gIG5vdGUgb3ZlciBCLCBCQTogaWYgYWxsIG1lbWJlcnMgbGVmdFxuICBCQSAtPj4gQjogRzpnaWRCOiBFTVBUWVxuXG4gIG5vdGUgb3ZlciBNLCBCOiA0Yi4gQSByZW1vdmVzIEIgZnJvbSBncm91cFxuXG4gIEEgLT4-IEFBOiBHOmdpZEEgUkVNIEM6aWRBQlxuICBBQSAtPj4gQTogRzpnaWRBIE9LXG4gIEFBIC0-PiBCQTogdmlhIGdpZEFCOiBPVVRcbiAgbm90ZSBvdmVyIEJBOiByZW1vdmUgZ2lkQkEsIGFsbCBnaWRCTVxuICBCQSAtPj4gQjogRzpnaWRCIE9VVCBDOmlkQkFcblxuICBub3RlIG92ZXIgQUE6IHJlbW92ZSBnaWRBQlxuICBBQSAtPj4gQTogRzpnaWRBIE9LXG5cbiAgbm90ZSBvdmVyIE0sIEI6IGJlbG93IHN0ZXBzIGhhcHBlbiBmb3IgZWFjaCBleGlzdGluZyBtZW1iZXIgTVxuXG4gIEFBIC0-PiBNQTogdmlhIGdpZEFNOiBSRU0gQzptaWRCXG4gIG5vdGUgb3ZlciBNQTogcmVtb3ZlIGdpZE1CXG4gIE1BIC0-PiBBQTogdmlhIGdpZE1BOiBSRU1EIEM6bWlkQlxuICBNQSAtPj4gTTogRzpnaWRNIFJFTUQgQzppZE1CIEM6aWRNQTxicj4oQiByZW1vdmVkIGJ5IEEpXG5cbiAgbm90ZSBvdmVyIEEsIEFBOiBvbmNlIGFsbCBtZW1iZXJzIHJlbW92ZWQgQlxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgUkVNRCBDOmlkQUI8YnI-KEIgcmVtb3ZlZCBieSB0aGlzIGFnZW50KVxuXG4gIG5vdGUgb3ZlciBNLCBCOiA0Yy4gQSBkZWxldGVzIGdyb3VwXG4gIEEgLT4-IEFBOiBHOmdpZEEgREVMXG4gIEFBIC0-PiBBOiBHOmdpZEEgT0tcbiAgXG4gIEFBIC0-PiBCQTogdmlhIGdpZEFCOiBERUxcbiAgbm90ZSBvdmVyIEJBOiByZW1vdmUgYWxsIGdyb3VwIGNvbm5lY3Rpb25zIGFuZCBtZXNzYWdlc1xuICBCQSAtPj4gQjogRzpnaWRCIERFTEQgQzppZEJBPGJyPihncm91cCBkZWxldGVkIGJ5IEEpXG4gIEJBIC0-PiBBQTogdmlhIGdpZEJBOiBERUxEXG4gIEFBIC0-PiBBOiBHOmdpZEEgREVMRCBDOmlkQUJcblxuICBBQSAtPj4gTUE6IHZpYSBnaWRBTTogREVMXG4gIG5vdGUgb3ZlciBNQTogcmVtb3ZlIGFsbCBncm91cCBjb25uZWN0aW9ucyBhbmQgbWVzc2FnZXNcbiAgTUEgLT4-IE06IEc6Z2lkTSBERUxEIEM6aWRNQTxicj4oZ3JvdXAgZGVsZXRlZCBieSBBKVxuICBNQSAtPj4gQUE6IHZpYSBnaWRNQTogREVMRFxuICBBQSAtPj4gQTogRzpnaWRBIERFTEQgQzppZEFNXG5cbiAgQUEgLT4-IEE6IEc6Z2lkQSBERUxEPGJyPihncm91cCBkZWxldGVkIGJ5IHRoaXMgYWdlbnQgLSBhbGwgY29uZmlybWVkKVxuIiwibWVybWFpZCI6e30sInVwZGF0ZUVkaXRvciI6ZmFsc2V9), the source is [here](./groups.mmd). + +![sequence digram for group operations](https://mermaid.ink/svg/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gIHBhcnRpY2lwYW50IE0gYXMgRXhpc3Rpbmc8YnI-bWVtYmVyIChNKVxuICBwYXJ0aWNpcGFudCBNQSBhcyBFeGlzdGluZzxicj5tZW1iZXI8YnI-YWdlbnQgKE1BKVxuICBwYXJ0aWNpcGFudCBBIGFzIEFsaWNlIChBKVxuICBwYXJ0aWNpcGFudCBBQSBhcyBBbGljZSdzPGJyPmFnZW50IChBQSlcbiAgcGFydGljaXBhbnQgQkEgYXMgQm9iJ3M8YnI-YWdlbnQgKEJBKVxuICBwYXJ0aWNpcGFudCBCIGFzIEJvYiAoQilcblxuICBub3RlIG92ZXIgQSwgQUE6IDEuIGNyZWF0ZSBuZXcgZ3JvdXAgKG5vIG1lbWJlcnMpXG4gIEEgLT4-IEFBOiBHOmdpZEE_IE5FVzxicj4oZ2lkQSAtIGdyb3VwIElEIG9mIHRoaXMgZ3JvdXAgZm9yIEEsPGJyPmNhbiBiZSBnZW5lcmF0ZWQgYnkgdGhlIGFnZW50KVxuXG4gIG5vdGUgb3ZlciBBQTogY3JlYXRlIFwiaW50ZXJuYWxcIiBicm9hZGNhc3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBncm91cDxicj4oQjogTkVXKVxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgT0tcblxuICBub3RlIG92ZXIgQSwgQkE6IDIuIGFkZCBCb2IgdG8gZ3JvdXBcblxuICBBIC0-PiBBQTogQzppZEFCIElOVFJPIEc6Z2lkQSBnSW5mbzxicj4oaWRBQiAtIGNvbm4gYWxpYXMgQSBoYXMgZm9yIEIpXG4gIFxuICBub3RlIG92ZXIgQUE6IGdlbmVyYXRlIG5ldyByYW5kb20gSUQgZm9yIG1lbWJlciBCIChtaWRCLCB1bmlxdWUgcGVyIGdyb3VwKTxicj5pbml0aWF0ZSBcImludGVybmFsXCIgY29ubmVjdGlvbiBnaWRBQiBmb3IgQiBpbiBncm91cDxicj4oaW50ZXJuYWwgbWVhbnMgdGhhdCBpdCBpcyBub3QgdmlzaWJsZSB0byB0aGUgY2xpZW50czxicj5hbmQgY2Fubm90IGJlIHVzZWQgd2l0aCBjbGllbnQgY29tbWFuZHMpXG5cbiAgQUEgLT4-IEJBOiB2aWEgaWRBQjogR1JPVVAgQzptaWRCIGc6Z0ludkFCIGdJbmZvXG4gIEJBIC0-PiBCOiBDOmlkQkEgUkVRIEc6aW52SUQgZ0luZm88YnI-KGludklEIC0gdG8gcmVmZXIgdG8gaXQgaW4gQUNQVClcbiAgQiAtPj4gQkE6IEc6Z2lkQj8gQUNQVCBHOmludklEPGJyPihSSkNUIEc6aW52SUQgY291bGQgYmUgYWRkZWQpXG5cbiAgbm90ZSBvdmVyIEJBOiBjcmVhdGUgZ3JvdXAgYW5kIFwiaW50ZXJuYWxcIiBicm9hZGNhc3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBncm91cDxicj4oQjogTkVXKVxuXG4gIEJBIC0-PiBCOiBHOmdpZEIgT0tcblxuICBCQSAtPj4gQUE6IGVzdGFibGlzaCBpbnRlcm5hbCBjb25uZWN0aW9uIGdpZEJBICh1c2luZyBnOmdJbnZBQikgZm9yIEEgaW4gZ3JvdXBcblxuICBub3RlIG92ZXIgQkEsIEFBOiBhZGQgY29ubmVjdGlvbnMgZ2lkQkEgYW5kIGdpZEFCIHRvIGJyb2FkY2FzdHM8YnI-KEI6IEFERClcbiBcbiAgQUEgLT4-IEE6IEc6Z2lkQSBDT04gQzppZEFCXG4gIEJBIC0-PiBCOiBHOmdpZEEgQ09OIEM6aWRCQVxuXG4gIG5vdGUgb3ZlciBNLCBCOiBGb3IgZWFjaCBleGlzdGluZyBtZW1iZXIgTTo8YnI-Y3JlYXRlIGFuZCBhY2NlcHQgaW50ZXJuYWwgaW50cm9kdWN0aW9uIGJldHdlZW4gY29ubmVjdGlvbnMsIHJlbGF0ZWQgdG8gdGhlIGdyb3VwLCB2aWEgZ2lkQUIvQkEvQU0vTUEsIGNvbm5lY3Rpb25zIGNyZWF0ZWQgYXJlIGdpZEJNIGFuZCBnaWRNQjxicj5UaGUgZmFjdCB0aGF0IHRoZSBpbnRyb2R1Y3Rpb24gYXJyaXZlcyB2aWEgY29ubmVjdGlvbiBhbGxvY2F0ZWQgZm9yIHRoZSBncm91cCwgYWxsb3dzIGFnZW50cyBpZGVudGlmeSBpdCBhcyBhIG5ldyBncm91cCBtZW1iZXIsIElEIHVzZWQgaW4gaW50cm9kdWN0aW9ucyBpcyBncm91cC1zY29wZWQgbWVtYmVyIElELlxuXG4gIG5vdGUgb3ZlciBBLCBCQTogb25jZSBhbGwgbWVtYmVycyB3ZXJlIHNlbnQgdG8gQlxuICBBQSAtPj4gQkE6IHZpYSBnaWRBQjogTUVNIEM6bWlkQlxuXG4gIG5vdGUgb3ZlciBCQSwgQjogb25jZSBhbGwgbWVtYmVycyBhcmUgY29ubmVjdGVkXG4gIEJBIC0-PiBCOiBHOmdpZEIgTUVNXG5cbiAgbm90ZSBvdmVyIEEsIEFBOiBvbmNlIGFsbCBtZW1iZXJzIHJlcG9ydGVkIGNvbm5lY3Rpb25cbiAgQUEgLT4-IEE6IEc6Z2lkQSBNRU0gQzppZEFCXG5cbiAgbm90ZSBvdmVyIE0sIEFBOiBmb3IgZWFjaCBtZW1iZXIgTVxuXG4gIEFBIC0-PiBNQTogdmlhIGdpZEFNOiBNRU0gQzptaWRCXG4gIE1BIC0-PiBNOiBHOmdpZE0gTUVNIEM6aWRNQlxuICBcbiAgbm90ZSBvdmVyIE0sIEI6IDMuIEIgc2VuZHMgbWVzc2FnZSB0byB0aGUgZ3JvdXBcblxuICBCIC0-PiBCQTogRzpnaWRCIFNFTkQgbXNnXG5cbiAgbm90ZSBvdmVyIEJBOiBzZW5kIG1lc3NhZ2UgdmlhIGFzc29jaWF0ZWQgYnJvYWRjYXN0IGFuZCByZXNwb25kIHRvIGNsaWVudCB3aXRoIFNFTlQgbm90aWZpY2F0aW9uc1xuXG4gIEJBIC0-PiBCOiBHOmdpZEIgU0VOVCBDOmlkQkEgaW50TXNnSURcbiAgQkEgLT4-IEI6IEc6Z2lkQiBTRU5UIEM6aWRCTSBpbnRNc2dJRFxuICBcbiAgbm90ZSBvdmVyIEJBLCBCOiBvbmNlIHNlbnQgdG8gYWxsXG4gIEJBIC0-PiBCOiBHOmdpZEIgU0VOVCBpbnRNc2dJRFxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgTVNHIEM6aWRBQiBpbnRNc2dJRCBtc2dkYXRhXG4gIEEgLT4-IEFBOiBHOmdpZEEgQUNLIGludE1zZ0lEXG4gIEFBIC0-PiBCQTogdmlhIGdpZEFCOiBSQ1ZEIGV4dE1zZ0lEIGhhc2ggc2lnXG4gIEJBIC0-PiBCOiBHOmdpZEEgUkNWRCBDOmlkQkEgaW50TXNnSUQgc3RhdHVzPGJyPihzdGF0dXMgLSBtZXNzYWdlIGludGVncml0eSBjaGVjaylcblxuICBNQSAtPj4gTTogRzpnaWRNIE1TRyBDOmlkTUIgaW50TXNnSUQgbXNnZGF0YVxuICBNIC0-PiBNQTogRzpnaWRNIEFDSyBpbnRNc2dJRFxuICBNQSAtPj4gQkE6IHZpYSBnaWRNQjogUkNWRCBleHRNc2dJRCBoYXNoIHNpZ1xuICBCQSAtPj4gQjogRzpnaWRNIFJDVkQgQzppZEJNIGludE1zZ0lEIHN0YXR1c1xuXG4gIG5vdGUgb3ZlciBCQSwgQjogb25jZSByZWNlaXZlZCBieSBhbGxcbiAgQkEgLT4-IEI6IEc6Z2lkTSBSQ1ZEIGludE1zZ0lEIHN0YXR1c1xuXG4gIG5vdGUgb3ZlciBNLCBCOiA0YS4gQSBsZWF2ZXMgZ3JvdXBcblxuICBBIC0-PiBBQTogRzpnaWRBIExFQVZFXG4gIEFBIC0-PiBBOiBHOmdpZEEgT0tcbiAgQUEgLT4-IEJBOiB2aWEgZ2lkQUI6IExFRlRcbiAgbm90ZSBvdmVyIEFBOiByZW1vdmUgZ2lkQUIsIHJlbW92ZSBmcm9tIGJyb2FkY2FzdFxuICBub3RlIG92ZXIgQkE6IHJlbW92ZSBnaWRCQSwgcmVtb3ZlIGZyb20gYnJvYWRjYXN0XG4gIEJBIC0-PiBCOiBHOmdpZEIgTEVGVCBDOmlkQkFcblxuICBBQSAtPj4gTUE6IHZpYSBnaWRBTTogTEVGVFxuICBub3RlIG92ZXIgQUE6IHJlbW92ZSBnaWRBTSwgcmVtb3ZlIGZyb20gYnJvYWRjYXN0XG4gIG5vdGUgb3ZlciBNQTogcmVtb3ZlIGdpZE1BLCByZW1vdmUgZnJvbSBicm9hZGNhc3RcbiAgTUEgLT4-IE06IEc6Z2lkTSBMRUZUIEM6aWRNQVxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgTEVGVFxuXG4gIG5vdGUgb3ZlciBCLCBCQTogaWYgYWxsIG1lbWJlcnMgbGVmdFxuICBCQSAtPj4gQjogRzpnaWRCOiBFTVBUWVxuXG4gIG5vdGUgb3ZlciBNLCBCOiA0Yi4gQSByZW1vdmVzIEIgZnJvbSBncm91cFxuXG4gIEEgLT4-IEFBOiBHOmdpZEEgUkVNIEM6aWRBQlxuICBBQSAtPj4gQTogRzpnaWRBIE9LXG4gIEFBIC0-PiBCQTogdmlhIGdpZEFCOiBPVVRcbiAgbm90ZSBvdmVyIEJBOiByZW1vdmUgZ2lkQkEsIGFsbCBnaWRCTVxuICBCQSAtPj4gQjogRzpnaWRCIE9VVCBDOmlkQkFcblxuICBub3RlIG92ZXIgQUE6IHJlbW92ZSBnaWRBQlxuICBBQSAtPj4gQTogRzpnaWRBIE9LXG5cbiAgbm90ZSBvdmVyIE0sIEI6IGJlbG93IHN0ZXBzIGhhcHBlbiBmb3IgZWFjaCBleGlzdGluZyBtZW1iZXIgTVxuXG4gIEFBIC0-PiBNQTogdmlhIGdpZEFNOiBSRU0gQzptaWRCXG4gIG5vdGUgb3ZlciBNQTogcmVtb3ZlIGdpZE1CXG4gIE1BIC0-PiBBQTogdmlhIGdpZE1BOiBSRU1EIEM6bWlkQlxuICBNQSAtPj4gTTogRzpnaWRNIFJFTUQgQzppZE1CIEM6aWRNQTxicj4oQiByZW1vdmVkIGJ5IEEpXG5cbiAgbm90ZSBvdmVyIEEsIEFBOiBvbmNlIGFsbCBtZW1iZXJzIHJlbW92ZWQgQlxuXG4gIEFBIC0-PiBBOiBHOmdpZEEgUkVNRCBDOmlkQUI8YnI-KEIgcmVtb3ZlZCBieSB0aGlzIGFnZW50KVxuXG4gIG5vdGUgb3ZlciBNLCBCOiA0Yy4gQSBkZWxldGVzIGdyb3VwXG4gIEEgLT4-IEFBOiBHOmdpZEEgREVMXG4gIEFBIC0-PiBBOiBHOmdpZEEgT0tcbiAgXG4gIEFBIC0-PiBCQTogdmlhIGdpZEFCOiBERUxcbiAgbm90ZSBvdmVyIEJBOiByZW1vdmUgYWxsIGdyb3VwIGNvbm5lY3Rpb25zIGFuZCBtZXNzYWdlc1xuICBCQSAtPj4gQjogRzpnaWRCIERFTEQgQzppZEJBPGJyPihncm91cCBkZWxldGVkIGJ5IEEpXG4gIEJBIC0-PiBBQTogdmlhIGdpZEJBOiBERUxEXG4gIEFBIC0-PiBBOiBHOmdpZEEgREVMRCBDOmlkQUJcblxuICBBQSAtPj4gTUE6IHZpYSBnaWRBTTogREVMXG4gIG5vdGUgb3ZlciBNQTogcmVtb3ZlIGFsbCBncm91cCBjb25uZWN0aW9ucyBhbmQgbWVzc2FnZXNcbiAgTUEgLT4-IE06IEc6Z2lkTSBERUxEIEM6aWRNQTxicj4oZ3JvdXAgZGVsZXRlZCBieSBBKVxuICBNQSAtPj4gQUE6IHZpYSBnaWRNQTogREVMRFxuICBBQSAtPj4gQTogRzpnaWRBIERFTEQgQzppZEFNXG5cbiAgQUEgLT4-IEE6IEc6Z2lkQSBERUxEPGJyPihncm91cCBkZWxldGVkIGJ5IHRoaXMgYWdlbnQgLSBhbGwgY29uZmlybWVkKVxuIiwibWVybWFpZCI6e30sInVwZGF0ZUVkaXRvciI6ZmFsc2V9) + +## Relevant external documents + +[Signal group protocol](https://signal.org/blog/private-groups/) + +[mpOTR](https://cypherpunks.ca/~iang/pubs/mpotr.pdf) + +[Threema whitepaper](https://threema.ch/press-files/cryptography_whitepaper.pdf) diff --git a/rfcs/2021-05-23-introduction.md b/rfcs/2021-05-23-introduction.md new file mode 100644 index 000000000..6212fcf3f --- /dev/null +++ b/rfcs/2021-05-23-introduction.md @@ -0,0 +1,41 @@ +# SMP agent introduction + +## Problem + +Allow an agent client to connect two connections it has directly, with the agent acting as an out-of-band channel. + +It can be used both separately as part of some client functionality, and as part of group protocol. + +## Solution + +A protocol with commands and message envelopes to exchange the information between parties to establish connection. + +### Commands and messages + +Below commands are for the scenario when A introduces B to M. + +- command `C:idAB INTRO C:idAM infoM` - initiate introduction of the connection cIdB to connection cIdM (response is `C:idAB OK`) +- message `C:idBA REQ C:invId infoM` - notification to confirm introduction +- command `C:idBM? ACPT C:invId` - accept offer to be introduced (response is `C:idBM OK`, followed by `C:idBM CON`) +- message `C:idBM CON` - confirmation that connection is established to both introduced parties +- message `C:idAB CON C:idAM` - confirmation that connection is established to the introducer + +### Agent envelopes + +- `INTRO C:extIntroIdM infoM` - new introduction offered by introducer +- `INV C:extIntroIdB prv:invBM infoB` - invitation to join connection from B to M sent via A +- `REQ C:extIntroIdB prv:invBM infoB` - new introduction forwarded by the introducer +- `CON C:extIntroId` - confirmation that the connection is established sent by both introduced parties to the introducer + +## Namespace + +Given that the introduction objects are short lived, they should not reuse the same commands or share the same namespace as connections, broadcasts and groups, but they probably should share the namespace with group and connection invitations. + +## Introduction protocol costs + +5 messages + cost to establish a connection + + +The [sequence digram for introduction](https://mermaid.ink/img/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gIHBhcnRpY2lwYW50IEEgYXMgQWxpY2UgKEEpIC0gdGhlIGludHJvZHVjZXJcbiAgcGFydGljaXBhbnQgQUEgYXMgQWxpY2Unczxicj5hZ2VudCAoQUEpXG4gIHBhcnRpY2lwYW50IEIgYXMgQm9iIChCKSAtIGludHJvZHVjZWRcbiAgcGFydGljaXBhbnQgQkEgYXMgQm9iJ3M8YnI-YWdlbnQgKEJBKVxuICBwYXJ0aWNpcGFudCBNIGFzIE1hcmsgKE0pIC0gaW50cm9kdWNlZCB0b1xuICBwYXJ0aWNpcGFudCBNQSBhcyBNYXJrJ3M8YnI-YWdlbnQgKE1BKVxuXG4gIG5vdGUgb3ZlciBBLCBBQTogMS4gY3JlYXRlIGludHJvZHVjdGlvblxuICBBIC0-PiBBQTogQzppZEFCIElOVFJPIEM6aWRBTSBpbmZvTTxicj4oaWRBQiAtIGNvbm4gYWxpYXMgQSBoYXMgZm9yIEIsPGJyPmlkQU0gLSBmb3IgTSlcbiAgQUEgLT4-IEE6IEM6aWRBQiBPS1xuXG4gIG5vdGUgb3ZlciBBLCBCQTogMi4gc2VuZCBpbnRybyB0byBCb2JcblxuICBBQSAtPj4gQkE6IHZpYSBpZEFCOiBJTlRSTyBDOmV4dEludHJvSWRNIGluZm9NXG4gIEJBIC0-PiBCOiBDOmlkQkEgUkVRIEM6aW50SW50cm9JZE0gaW5mb01cbiAgQiAtPj4gQkE6IEM6aWRCTT8gQUNQVCBDOmludEludHJvSWRNXG4gIEJBIC0-PiBCOiBDOmlkQk0gT0tcblxuICBub3RlIG92ZXIgQkE6IDMuIGNyZWF0ZSBjb25uZWN0aW9uIGZvciAgTSBpZEJNXG5cbiAgQkEgLT4-IEFBOiB2aWEgaWRCQTogSU5WIEM6ZXh0SW50cm9JZE0gcHJ2OmludkJNIGluZm9CXG5cbiAgbm90ZSBvdmVyIEFBLCBNOiA0LiBzZW5kIGludHJvIHRvIE1hcmtcblxuICBBQSAtPj4gTUE6IHZpYSBpZEFNOiBSRVEgQzpleHRJbnRyb0lkQiBwcnY6aW52Qk0gaW5mb0JcblxuICBub3RlIG92ZXIgTUEsIEI6IDUuIE1hcmsgY29ubmVjdHMgdG8gQm9iXG5cbiAgTUEgLT4-IE06IEM6aWRNQSBSRVEgQzppbnRJbnRyb0lkQiBpbmZvQlxuICBNIC0-PiBNQTogQzppZE1CPyBBQ1BUIEM6aW50SW50cm9JZEJcbiAgTUEgLT4-IE06IEM6aWRNQiBPS1xuXG4gIE1BIC0-PiBCQTogIGVzdGFibGlzaCBjb25uZWN0aW9uIGlkQk0gLT4gaWRNQlxuXG4gIG5vdGUgb3ZlciBBLCBNQTogNi4gbm90aWZ5IGFsbCBjbGllbnRzXG5cbiAgTUEgLT4-IE06IEM6aWRNQiBDT05cbiAgTUEgLT4-IEFBOiB2aWEgaWRNQTogQ09OIEM6ZXh0SW50cm9JZEJcbiAgQkEgLT4-IEI6IEM6aWRCTSBDT05cbiAgQkEgLT4-IEFBOiB2aWEgaWRCQTogQ09OIEM6ZXh0SW50cm9JZEJcbiAgQUEgLT4-IEE6IEM6aWRBQiBDT04gQzppZEFNXG4iLCJtZXJtYWlkIjp7fSwidXBkYXRlRWRpdG9yIjpmYWxzZX0), the source is [here](./intro.mmd). + +![sequence digram for introduction](https://mermaid.ink/svg/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gIHBhcnRpY2lwYW50IEEgYXMgQWxpY2UgKEEpIC0gdGhlIGludHJvZHVjZXJcbiAgcGFydGljaXBhbnQgQUEgYXMgQWxpY2Unczxicj5hZ2VudCAoQUEpXG4gIHBhcnRpY2lwYW50IEIgYXMgQm9iIChCKSAtIGludHJvZHVjZWRcbiAgcGFydGljaXBhbnQgQkEgYXMgQm9iJ3M8YnI-YWdlbnQgKEJBKVxuICBwYXJ0aWNpcGFudCBNIGFzIE1hcmsgKE0pIC0gaW50cm9kdWNlZCB0b1xuICBwYXJ0aWNpcGFudCBNQSBhcyBNYXJrJ3M8YnI-YWdlbnQgKE1BKVxuXG4gIG5vdGUgb3ZlciBBLCBBQTogMS4gY3JlYXRlIGludHJvZHVjdGlvblxuICBBIC0-PiBBQTogQzppZEFCIElOVFJPIEM6aWRBTSBpbmZvTTxicj4oaWRBQiAtIGNvbm4gYWxpYXMgQSBoYXMgZm9yIEIsPGJyPmlkQU0gLSBmb3IgTSlcbiAgQUEgLT4-IEE6IEM6aWRBQiBPS1xuXG4gIG5vdGUgb3ZlciBBLCBCQTogMi4gc2VuZCBpbnRybyB0byBCb2JcblxuICBBQSAtPj4gQkE6IHZpYSBpZEFCOiBJTlRSTyBDOmV4dEludHJvSWRNIGluZm9NXG4gIEJBIC0-PiBCOiBDOmlkQkEgUkVRIEM6aW50SW50cm9JZE0gaW5mb01cbiAgQiAtPj4gQkE6IEM6aWRCTT8gQUNQVCBDOmludEludHJvSWRNXG4gIEJBIC0-PiBCOiBDOmlkQk0gT0tcblxuICBub3RlIG92ZXIgQkE6IDMuIGNyZWF0ZSBjb25uZWN0aW9uIGZvciAgTSBpZEJNXG5cbiAgQkEgLT4-IEFBOiB2aWEgaWRCQTogSU5WIEM6ZXh0SW50cm9JZE0gcHJ2OmludkJNIGluZm9CXG5cbiAgbm90ZSBvdmVyIEFBLCBNOiA0LiBzZW5kIGludHJvIHRvIE1hcmtcblxuICBBQSAtPj4gTUE6IHZpYSBpZEFNOiBSRVEgQzpleHRJbnRyb0lkQiBwcnY6aW52Qk0gaW5mb0JcblxuICBub3RlIG92ZXIgTUEsIEI6IDUuIE1hcmsgY29ubmVjdHMgdG8gQm9iXG5cbiAgTUEgLT4-IE06IEM6aWRNQSBSRVEgQzppbnRJbnRyb0lkQiBpbmZvQlxuICBNIC0-PiBNQTogQzppZE1CPyBBQ1BUIEM6aW50SW50cm9JZEJcbiAgTUEgLT4-IE06IEM6aWRNQiBPS1xuXG4gIE1BIC0-PiBCQTogIGVzdGFibGlzaCBjb25uZWN0aW9uIGlkQk0gLT4gaWRNQlxuXG4gIG5vdGUgb3ZlciBBLCBNQTogNi4gbm90aWZ5IGFsbCBjbGllbnRzXG5cbiAgTUEgLT4-IE06IEM6aWRNQiBDT05cbiAgTUEgLT4-IEFBOiB2aWEgaWRNQTogQ09OIEM6ZXh0SW50cm9JZEJcbiAgQkEgLT4-IEI6IEM6aWRCTSBDT05cbiAgQkEgLT4-IEFBOiB2aWEgaWRCQTogQ09OIEM6ZXh0SW50cm9JZEJcbiAgQUEgLT4-IEE6IEM6aWRBQiBDT04gQzppZEFNXG4iLCJtZXJtYWlkIjp7fSwidXBkYXRlRWRpdG9yIjpmYWxzZX0) diff --git a/rfcs/groups.mmd b/rfcs/groups.mmd new file mode 100644 index 000000000..c9151c015 --- /dev/null +++ b/rfcs/groups.mmd @@ -0,0 +1,135 @@ +sequenceDiagram + participant M as Existing
member (M) + participant MA as Existing
member
agent (MA) + participant A as Alice (A) + participant AA as Alice's
agent (AA) + participant BA as Bob's
agent (BA) + participant B as Bob (B) + + note over A, AA: 1. create new group (no members) + A ->> AA: G:gidA? NEW
(gidA - group ID of this group for A,
can be generated by the agent) + + note over AA: create "internal" broadcast associated with the group
(B: NEW) + + AA ->> A: G:gidA OK + + note over A, BA: 2. add Bob to group + + A ->> AA: C:idAB INTRO G:gidA gInfo
(idAB - conn alias A has for B) + + note over AA: generate new random ID for member B (midB, unique per group)
initiate "internal" connection gidAB for B in group
(internal means that it is not visible to the clients
and cannot be used with client commands) + + AA ->> BA: via idAB: GROUP C:midB g:gInvAB gInfo + BA ->> B: C:idBA REQ G:invID gInfo
(invID - to refer to it in ACPT) + B ->> BA: G:gidB? ACPT G:invID
(RJCT G:invID could be added) + + note over BA: create group and "internal" broadcast associated with the group
(B: NEW) + + BA ->> B: G:gidB OK + + BA ->> AA: establish internal connection gidBA (using g:gInvAB) for A in group + + note over BA, AA: add connections gidBA and gidAB to broadcasts
(B: ADD) + + AA ->> A: G:gidA CON C:idAB + BA ->> B: G:gidA CON C:idBA + + note over M, B: For each existing member M:
create and accept internal introduction between connections, related to the group, via gidAB/BA/AM/MA, connections created are gidBM and gidMB
The fact that the introduction arrives via connection allocated for the group, allows agents identify it as a new group member, ID used in introductions is group-scoped member ID. + + note over A, BA: once all members were sent to B + AA ->> BA: via gidAB: MEM C:midB + + note over BA, B: once all members are connected + BA ->> B: G:gidB MEM + + note over A, AA: once all members reported connection + AA ->> A: G:gidA MEM C:idAB + + note over M, AA: for each member M + + AA ->> MA: via gidAM: MEM C:midB + MA ->> M: G:gidM MEM C:idMB + + note over M, B: 3. B sends message to the group + + B ->> BA: G:gidB SEND msg + + note over BA: send message via associated broadcast and respond to client with SENT notifications + + BA ->> B: G:gidB SENT C:idBA intMsgID + BA ->> B: G:gidB SENT C:idBM intMsgID + + note over BA, B: once sent to all + BA ->> B: G:gidB SENT intMsgID + + AA ->> A: G:gidA MSG C:idAB intMsgID msgdata + A ->> AA: G:gidA ACK intMsgID + AA ->> BA: via gidAB: RCVD extMsgID hash sig + BA ->> B: G:gidA RCVD C:idBA intMsgID status
(status - message integrity check) + + MA ->> M: G:gidM MSG C:idMB intMsgID msgdata + M ->> MA: G:gidM ACK intMsgID + MA ->> BA: via gidMB: RCVD extMsgID hash sig + BA ->> B: G:gidM RCVD C:idBM intMsgID status + + note over BA, B: once received by all + BA ->> B: G:gidM RCVD intMsgID status + + note over M, B: 4a. A leaves group + + A ->> AA: G:gidA LEAVE + AA ->> A: G:gidA OK + AA ->> BA: via gidAB: LEFT + note over AA: remove gidAB, remove from broadcast + note over BA: remove gidBA, remove from broadcast + BA ->> B: G:gidB LEFT C:idBA + + AA ->> MA: via gidAM: LEFT + note over AA: remove gidAM, remove from broadcast + note over MA: remove gidMA, remove from broadcast + MA ->> M: G:gidM LEFT C:idMA + + AA ->> A: G:gidA LEFT + + note over B, BA: if all members left + BA ->> B: G:gidB: EMPTY + + note over M, B: 4b. A removes B from group + + A ->> AA: G:gidA REM C:idAB + AA ->> A: G:gidA OK + AA ->> BA: via gidAB: OUT + note over BA: remove gidBA, all gidBM + BA ->> B: G:gidB OUT C:idBA + + note over AA: remove gidAB + AA ->> A: G:gidA OK + + note over M, B: below steps happen for each existing member M + + AA ->> MA: via gidAM: REM C:midB + note over MA: remove gidMB + MA ->> AA: via gidMA: REMD C:midB + MA ->> M: G:gidM REMD C:idMB C:idMA
(B removed by A) + + note over A, AA: once all members removed B + + AA ->> A: G:gidA REMD C:idAB
(B removed by this agent) + + note over M, B: 4c. A deletes group + A ->> AA: G:gidA DEL + AA ->> A: G:gidA OK + + AA ->> BA: via gidAB: DEL + note over BA: remove all group connections and messages + BA ->> B: G:gidB DELD C:idBA
(group deleted by A) + BA ->> AA: via gidBA: DELD + AA ->> A: G:gidA DELD C:idAB + + AA ->> MA: via gidAM: DEL + note over MA: remove all group connections and messages + MA ->> M: G:gidM DELD C:idMA
(group deleted by A) + MA ->> AA: via gidMA: DELD + AA ->> A: G:gidA DELD C:idAM + + AA ->> A: G:gidA DELD
(group deleted by this agent - all confirmed) diff --git a/rfcs/intro.mmd b/rfcs/intro.mmd new file mode 100644 index 000000000..3c7c7e06f --- /dev/null +++ b/rfcs/intro.mmd @@ -0,0 +1,42 @@ +sequenceDiagram + participant A as Alice (A) - the introducer + participant AA as Alice's
agent (AA) + participant B as Bob (B) - introduced + participant BA as Bob's
agent (BA) + participant M as Mark (M) - introduced to + participant MA as Mark's
agent (MA) + + note over A, AA: 1. create introduction + A ->> AA: C:idAB INTRO C:idAM infoM
(idAB - conn alias A has for B,
idAM - for M) + AA ->> A: C:idAB OK + + note over A, BA: 2. send intro to Bob + + AA ->> BA: via idAB: INTRO C:extIntroIdM infoM + BA ->> B: C:idBA REQ C:intIntroIdM infoM + B ->> BA: C:idBM? ACPT C:intIntroIdM + BA ->> B: C:idBM OK + + note over BA: 3. create connection for M idBM + + BA ->> AA: via idBA: INV C:extIntroIdM invBM infoB + + note over AA, M: 4. send intro to Mark + + AA ->> MA: via idAM: REQ C:extIntroIdB invBM infoB + + note over MA, B: 5. Mark connects to Bob + + MA ->> M: C:idMA REQ C:intIntroIdB infoB + M ->> MA: C:idMB? ACPT C:intIntroIdB + MA ->> M: C:idMB OK + + MA ->> BA: establish connection idBM -> idMB + + note over A, MA: 6. notify all clients + + MA ->> M: C:idMB CON + MA ->> AA: via idMA: CON C:extIntroIdB + BA ->> B: C:idBM CON + BA ->> AA: via idBA: CON C:extIntroIdB + AA ->> A: C:idAB CON C:idAM diff --git a/rfcs/protocol_overview.md b/rfcs/protocol_overview.md new file mode 100644 index 000000000..1ff6ff4a5 --- /dev/null +++ b/rfcs/protocol_overview.md @@ -0,0 +1,146 @@ +# Overview of SMP agent protocol commands + +## Connections + +### Commands and messages + +A initiates connection, B accepts + +- command `C:idB? NEW` - create connection +- message `C:idB INV cInv` +- command `C:idA? JOIN cInv replyMode` - join connection (response `OK`, followed by `CON`) +- *message* `C:idB REQ prv:invId infoB` - request from B joining sent to A (not implemented) +- *command* `C:idB ACPT prv:invId` - A confirms B joining (not implemented) +- message `C:id CON` - connection is established +- command `C:id SUB` - subscribe to connection +- message `C:id END` - unsubscribed from connection +- command `C:idB SEND msg` - send message +- message `C:idA SENT msgId` - confirmation that the message is sent +- message `C:id MSG msgId msgMeta msgIntegrity msgBody` - received message +- *command* `C:idB ACK msgId` - acknowledge message reception (not implemented) +- *message* `C:idA RCVD msgId msgIntegrity` - confirmation of message reception and integrity (not implemented) +- command `C:id OFF` - suspend connection +- command `C:id DEL` - delete connection +- message `C:id? OK` - command confirmation +- message `C:id? ERR e` - error + +### Envelopes + +- `MSG ` +- `HELLO verificationKey ackMode` +- `REPLY replyInv` + +## Broadcasts + +### Commands & messages + +- command `B:id? NEW` - create broadcast (response is `B:id OK`) +- command `B:id SEND msg` - broadcast message (response is multiple `C:id SENT msgId` or ERR, separately for each connection, followed by `B:id SENT msgId` once sent to all) +- message `B:id SENT msgId` - notification that the message is sent and its internal ID, same as SENT +- command `B:id ADD cId` - add existing connection to a broadcast (response is `B:id OK` or `ERR`, e.g. if bId is used) +- command `B:id REM cId` - remove connection from the broadcast (response is `REMD`) +- message `B:id REMD cId` - connection removed from the broadcast +- message `B:id EMPTY` - all connections were removed from the broadcast +- command `B:id DEL` - delete broadcast (response is `B:id OK`) +- command `B:id LS` - list connections in broadcast, response is `B:id MEM space_separated_connections` +- message `B:id MEM space_separated_connections` + +## Open/public connection + +### Commands + +- command `O:id? NEW` - create open connection +- message `O:id INV oInv` - open invitation +- command `C:id? JOIN oInv replyMode` - join connection (response `OK`, followed by `CON`) +- message `O:id REQ open:invId infoB` - confirmation from B joining sent to A +- command `C:idC? ACPT open:invId` - note, that it creates new connection, keeping OPEN connection +- command `O:id SUB` - subscribe to open connection +- message `O:id END` - unsubscribed from open connection +- command `O:id OFF` - suspend open connection +- command `O:id DEL` - delete open connection +- message `O:id? OK` - command confirmation +- message `O:id? ERR e` - error + +## Introductions + +### Commands + +- command `C:idAB INTRO C:idAM infoM` - introduce connection cIdB to connection cIdM (response is `OK`) +- message `C:idBA REQ C:invId infoM` - notification to confirm introduction +- command `C:idBM? ACPT C:invId` - accept offer to be introduced (response is `cIdBM OK`, followed by `ICON`) +- message `C:idBM CON` - confirmation that connection is established to both introduced parties +- message `C:idAB CON C:idAM` - confirmation that connection is established to the introducer + +### Envelopes + +- `INTRO C:extIntroIdM infoM` - new introduction offered by introducer +- `INV C:extIntroIdB prv:invBM infoB` - invitation to join connection from B to M sent via A (can be pub:) +- `REQ C:extIntroIdB prv:invBM infoB` - new introduction forwarded by introducer +- `CON C:extIntroIdM` - confirmation that the connection is established sent by both introduced parties to the introducer + +## Groups + +## Agent commands and messages syntax + +- command `G:gId? NEW` - create group (response is `G:gId OK`) +- command `C:cId INTRO G:gId gInfo` - add existing connection to a group +- message `C:cId REQ g:invID gInfo` - invitation to join the group +- command `G:gId? ACPT g:invId` - accept invitation (response is `G gId OK`) +- message `G:gId CON C:cId` - 2 connections created with some group member (both for group and direct messages) +- message `G:gId MEM [C:cId]` - connection created with all group members for a given member or current client +- command `G:gId SEND msg` - send message to group +- message `G:gId SENT msgId` - notification that the message is sent and its internal ID, same as SENT +- message `G:gId MSG C:cId msgId msgdata` - received group message from cId, msgdata is the same set of parameters as in `MSG` +- command `G:gId ACK msgId` - acknowledge message reception by the client +- message `G:gId RCVD t:cId msgId status` - message delivery notification +- command `G:gId LEAVE` - leave the group +- message `G:gId LEFT [C:cId]` - connection cId left the group +- command `G:gId REM C:cId` - remove group member (response is `gId OK`, followed by `GREMD` notification) +- message `G:gId REMD C:cId [C:cId]` - member removed +- message `G:gId OUT C:cId` - you are removed (see question below - should it be just a sequence of GLEFT?) +- message `G:gId EMPTY` - all members left the group and it is now empty +- command `G:gId DEL` - delete the group (response is `gId OK`) +- message `G:gId DELD [C:cId]` - group deleted + +## Agent message envelopes syntax + +- `GROUP C:mid G:inv gInfo` - invitation to join the group +- `MEM C:mid` - confirmation that member connected to all members +- `LEFT` - notification that member left the group +- `OUT` - you are removed from the group +- `REM C:mid` - remove member mid from the group +- `REMD C:mid` - confirmation that member is removed +- `DEL` - group is deleted +- `DELD` - confirmation that group is deleted + +## Commands and objects + +| Dir | Command / message | (C)onnection | (O)pen connection | (B)roadcast | (G)roup | +|:---------:|:--------------------:|:------------:|:-----------------:|:-----------:|:-------:| +| command | `t:id? NEW` | ✓ | ✓ | ✓ | ✓ | +| command | `C:id INTRO t:id info` | ✓ | - | - | ✓ | +| message | `t:id INV inv` | ✓ | ✓ | - | - | +| command | `C:id? JOIN inv replyMode info` | ✓ | - | - | - | +| message | `t:id REQ invId info` | ✓ | ✓ | - | ✓ | +| command | `t:id? ACPT invId` | ✓ | - | - | ✓ | +| message | `t:id CON [C:id]` | ✓ | - | - | ✓ | +| message | `t:id MEM [C:id]` | - | - | - | ✓ | +| command | `t:id SUB` | ✓ | ✓ | - | ✓ | +| message | `t:id END` | ✓ | ✓ | - | ✓ | +| command | `t:id OFF` | ✓ | ✓ | - | - | +| command | `t:id DEL` | ✓ | ✓ | ✓ | ✓ | +| message | `t:id DELD [C:Id]` | ✓ | ✓ | ✓ | ✓ | +| command | `t:id SEND msg` | ✓ | - | ✓ | ✓ | +| message | `t:id SENT [t':id] msgId` | ✓ | - | ✓ | ✓ | +| message | `t:id MSG [C:id] msgId msgdata` | ✓ | - | - | ✓ | +| command | `t:id ACK msgId` | ✓ | - | - | ✓ | +| message | `t:id RCVD [t':id] msgId status` | ✓ | - | - | ✓ | +| command | `t:id ADD C:id` | - | - | - | ✓ | +| command | `t:id REM C:id` | - | - | ✓ | ✓ | +| command | `t:id REMD C:id` | - | - | ✓ | ✓ | +| message | `t:id EMPTY` | - | - | ✓ | ✓ | +| message | `G:id OUT C:id` | - | - | - | ✓ | +| command | `t:id LS` | - | - | ✓ | ✓ | +| message | `t:id MS cIds` | - | - | ✓ | ✓ | +| command | `G:id LEAVE` | - | - | - | ✓ | +| message | `G:id LEFT [C:id]` | - | - | - | ✓ |