-
Notifications
You must be signed in to change notification settings - Fork 292
multistream-select-v2: Initial draft #701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MarcoPolo
wants to merge
1
commit into
master
Choose a base branch
from
mss-v2
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,265 @@ | ||
| # Multistream Select V2 | ||
|
|
||
| | Lifecycle Stage | Maturity | Status | Latest Revision | | ||
| | --------------- | ------------- | ------ | --------------- | | ||
| | 1A | Working Draft | Active | r1, 2025-11-13 | | ||
|
|
||
| Authors: [@raulk], [@marcopolo] | ||
|
|
||
| Interest Group: [@ppopth] | ||
|
|
||
| [@marcopolo]: https://github.com/marcopolo | ||
| [@ppopth]: https://github.com/ppopth | ||
| [@raulk]: https://github.com/raulk | ||
|
|
||
| ## Terminology | ||
|
|
||
| Server: The endpoint advertising its supported protocol strings. | ||
|
|
||
| Client: The endpoint receiving the advertisement and using protocol string | ||
| abbreviations when opening streams. | ||
|
|
||
| Abbreviation Tree: The tree data structure that determines the abbreviation to | ||
| use for a given protocol string. | ||
|
|
||
| Note, A peer can behave as both a client and server. For the purpose of defining | ||
| this protocol, it's useful to focus on the client/server interaction. | ||
|
|
||
| ## Abbreviation Tree | ||
|
|
||
| A list of protocol strings are abbreviated by creating a minimal hash prefix | ||
| tree. | ||
|
|
||
| ### Construction | ||
|
|
||
| Each protocol string is hashed and inserted into the tree as shallowly as | ||
| possible. Each node in the tree has 256 leaf branches representing a byte of the | ||
| hash (2^8). If multiple protocol strings share a common byte prefix, they are | ||
| distinguished the next level down the tree. | ||
|
|
||
| Each protocol string in the tree has a tombstone bit associated with it. This is | ||
| set to true if the protocol is currently not supported (but was previously). | ||
|
|
||
| A node in the tree may contain a value as well as children. This only happens | ||
| when introducing a new supported protocol introduces a conflict. This does not | ||
| happen on initial construction. | ||
|
|
||
| ### Example | ||
|
|
||
| ```txt | ||
| (root) | ||
| | | ||
| +-- 0xaa -> "/some-protocol/a/v1" | ||
| | | ||
| +-- 0xbb -> "/some-protocol/b/v1" | ||
| | | ||
| +-- 0xcc | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/c/v1" | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/c'/v1" | ||
| | | ||
| +-- 0xdd -> "/some-protocol/d/v1" tombstone=true | ||
| ``` | ||
|
|
||
| ### Inserting a New Protocol String | ||
|
|
||
| The protocol string is inserted into the tree as shallowly as possible. If there | ||
| is a conflict, the protocol string should be inserted one level down and | ||
| duplicate the conflicting protocol string to the new level if it is not | ||
| tombstoned. The conflicting protocol string MUST not removed from its original | ||
| position as it may still be referenced. | ||
|
|
||
| #### Example | ||
|
|
||
| Using the initial example as the initial state and we add three new protocol | ||
| strings: | ||
|
|
||
| 1. `"/new-protocol/foo"` that hashes to `0xaa02`. This example highlights a | ||
| conflict with an existing protocol string. | ||
| 2. `"/new-protocol/bar"` that hashes to `0xee...`. This example highlights no | ||
| conflicts and inserting shallowly. | ||
| 3. `"/new-protocol/d"` that hashes to `0xdd02`. This example highlights a | ||
| conflict with a tombstoned protocol string. | ||
|
|
||
| ```txt | ||
| (root) | ||
| | | ||
| +-- 0xaa -> "/some-protocol/a/v1" | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/a/v1" | ||
| | | | ||
| | +-- 0x02 -> "/new-protocol/foo" | ||
| | | ||
| +-- 0xbb -> "/some-protocol/b/v1" | ||
| | | ||
| +-- 0xcc | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/c/v1" | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/c'/v1" | ||
| | | ||
| +-- 0xdd -> "/some-protocol/d/v1" tombstone=true | ||
| | | | ||
| | +-- 0xdd01 -> "/new-protocol/d" | ||
| | | ||
| +-- 0xee -> "/new-protocol/bar" | ||
| ``` | ||
|
|
||
| ### Removing a Protocol String | ||
|
|
||
| For each instance of the protocol string in the tree, the tombstone bit is set | ||
| to true. The protocol string MUST not be removed from the tree as that could | ||
| lead to inconsistencies if a new protocol string is introduced with the same | ||
| prefix hash. | ||
|
|
||
| #### Example | ||
|
|
||
| Using the initial example as the initial state and we remove protocol | ||
| string `"/some-protocol/b/v1"`. | ||
|
|
||
| ```txt | ||
| (root) | ||
| | | ||
| +-- 0xaa -> "/some-protocol/a/v1" | ||
| | | ||
| +-- 0xbb -> "/some-protocol/b/v1" tombstone=true | ||
| | | ||
| +-- 0xcc | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/c/v1" | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/c'/v1" | ||
| | | ||
| +-- 0xdd -> "/some-protocol/d/v1" tombstone=true | ||
| ``` | ||
|
|
||
| ### Reintroducing a previously removed protocol string | ||
|
|
||
| For each instance of the protocol string in the tree, the tombstone bit should | ||
| be set to false. The protocol string should then be inserted into the tree as if | ||
| inserting a new protocol string. If the protocol string is already present as a | ||
| leaf node, no changes are required. | ||
|
|
||
| #### Example | ||
|
|
||
| Using the example for removing a protocol string as the initial state. We | ||
| reintroduce protocol string `"/some-protocol/b/v1"`. | ||
|
|
||
| ```txt | ||
| (root) | ||
| | | ||
| +-- 0xaa -> "/some-protocol/a/v1" | ||
| | | ||
| +-- 0xbb -> "/some-protocol/b/v1" | ||
| | | ||
| +-- 0xcc | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/c/v1" | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/c'/v1" | ||
| | | ||
| +-- 0xdd -> "/some-protocol/d/v1" tombstone=true | ||
| ``` | ||
|
|
||
| #### Example with a new leaf node | ||
|
|
||
| If the tombstoned protocol string is no longer at a leaf position we need to | ||
| insert a new protocol string, as well as untombstoning the existing protocol | ||
| string. | ||
|
|
||
| Initial State: | ||
|
|
||
| ```txt | ||
| (root) | ||
| | | ||
| +-- 0xaa -> "/some-protocol/a/v1" | ||
| | | ||
| +-- 0xbb -> "/some-protocol/b/v1" tombstone=true | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/b'/v1" | ||
| | | ||
| +-- 0xcc | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/c/v1" | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/c'/v1" | ||
| | | ||
| +-- 0xdd -> "/some-protocol/d/v1" tombstone=true | ||
| ``` | ||
|
|
||
| After reintroducing `"/some-protocol/b/v1"`: | ||
|
|
||
| ```txt | ||
| (root) | ||
| | | ||
| +-- 0xaa -> "/some-protocol/a/v1" | ||
| | | ||
| +-- 0xbb -> "/some-protocol/b/v1" | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/b/v1" | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/b'/v1" | ||
| | | ||
| +-- 0xcc | ||
| | | | ||
| | +-- 0x01 -> "/some-protocol/c/v1" | ||
| | | | ||
| | +-- 0x02 -> "/some-protocol/c'/v1" | ||
| | | ||
| +-- 0xdd -> "/some-protocol/d/v1" tombstone=true | ||
| ``` | ||
|
|
||
| ## Limits | ||
|
|
||
| Implementations SHOULD limit the number of protocol strings they track | ||
| (including tombstoned protocol strings). | ||
|
|
||
| ## Mapping Algorithm | ||
|
|
||
| A mapping algorithm maps a protocol string to byte array. This byte array is | ||
| used for the abbreviation tree. | ||
|
|
||
| SHA256 MUST be used for the mapping algorithm. | ||
|
|
||
| TODO: Do we want to consider faster keyed hashes? Risks complicating | ||
| implementations. | ||
|
|
||
| TODO: Do we need a hash function at all? Would an index into the list of a | ||
| server's protocols work instead? | ||
|
|
||
| ## Initial Server Client Exchange | ||
|
|
||
| When a client connects to a server, the server shares all the state necessary to | ||
| create an abbreviation tree it can use to communicate with the server. Namely: | ||
| the list of supported protocol strings, and the list of previously supported | ||
| protocol strings (tombstoned protocol strings). | ||
|
|
||
| The client's abbreviation tree will differ from the server's abbreviation tree | ||
| only in that protocol strings will only exist at leaf nodes in the client's | ||
| abbreviation tree. This is because non-leaf protocol strings only occur when | ||
| adding a protocol string to an existing tree. | ||
|
|
||
| # Multistream Select V2 | ||
|
|
||
| ## Wire Format | ||
|
|
||
| TODO define the wire format of multistream select v2. | ||
|
|
||
| ## Client opening a new stream | ||
|
|
||
| A client identifies the protocol string it wishes to use on a stream by the | ||
| minimal hash prefix as determined by the abbreviate stream. | ||
|
|
||
| ## Server accepting a new stream | ||
|
|
||
| The server identifies the protocol string by looking up the minimal hash prefix | ||
| in the tree. | ||
|
|
||
| ## Version Negotiation | ||
|
|
||
| Multistream Select V2 does not support negotiating different protocols on a | ||
| single stream like Multistream Select V1 does. A client specifies what protocol | ||
| they would like to use for a stream and MAY start sending protocol immediately. | ||
| If the server does not support this protocol, it MUST close the stream with | ||
| error code (TODO specify this). | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.