Skip to content
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

RFC: Tangle Message #17

Merged
merged 53 commits into from
Oct 25, 2021
Merged
Changes from 46 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3357004
add message rfc
Jul 28, 2020
805758f
add payload types
Jul 28, 2020
fa24ebb
corrections
Jul 28, 2020
c778814
add space
Jul 28, 2020
915cd2b
Add milestone payload
Aug 3, 2020
b973ccf
Remove dependency on payload validation
Aug 6, 2020
5803db6
change to lower case
Aug 25, 2020
4ce1327
change we to it
Aug 25, 2020
04b35a7
remove message pow section
Aug 25, 2020
67c8004
Remove empty lines
Aug 25, 2020
9d1f832
remove PoW questions
Aug 25, 2020
8ee6316
Allow 0 length payloads
Aug 25, 2020
2caf731
fix sentence
Aug 25, 2020
a426446
Remove bound
Aug 25, 2020
5eabf5e
unsigned data payload
Aug 25, 2020
7b003e2
Make capitalization consistent
Aug 25, 2020
385abff
Add serialization example
Aug 26, 2020
35b8653
add temporary links
Aug 26, 2020
c795980
fix serailization with byte array length
Aug 26, 2020
54b0a0a
remove nested payload
Aug 26, 2020
1150c72
Make serialization Pow Hash to have 9 trailing zeros
Aug 26, 2020
2a43097
Add indexation payload
Aug 30, 2020
cc15a51
Add indexation payload
Aug 30, 2020
3d92d83
use fixed size integers
luca-moser Sep 4, 2020
793378d
fixes payload type to uint32
luca-moser Sep 7, 2020
dcbf444
adds ByteArray/string type to types table
luca-moser Sep 7, 2020
8a69a4c
Fix link
Oct 29, 2020
0e5d060
add network id
Nov 9, 2020
98e7437
Fix serialization
Nov 10, 2020
e323b18
Change indexation validation rule
Nov 10, 2020
dd826e0
Change length to 32 bytes little endian
Nov 16, 2020
5843c38
Remove version and fix network identifier
Nov 16, 2020
d3a46d9
change nonce
Nov 16, 2020
d650bb8
Apply suggestions from technical writer
Nov 18, 2020
ecb8b66
change index validation criteria
Nov 24, 2020
92a2f73
Use blake2b for networkId
Nov 24, 2020
3b330c1
message must not be more than 32 kb
Nov 24, 2020
f4f94cd
Fix max message size and index encoding
Jan 12, 2021
4e9ecdd
Add number of parents
Jan 12, 2021
f1b5775
Index key is now a byte array
Feb 18, 2021
466d328
change parents rule to be between 1-8
Mar 2, 2021
d4eea48
remove core payload
Mar 9, 2021
2ef7705
Update 0017-message.md
Wollac Oct 20, 2021
e5d02e2
Update 0017-message.md
Wollac Oct 20, 2021
1ba4de5
Update 0017-message.md
Wollac Oct 20, 2021
d479e9e
Update 0017-message.md
Wollac Oct 20, 2021
c3ace55
Clarify ranges
Wollac Oct 20, 2021
5168461
Update 0017-message.md
Wollac Oct 20, 2021
f641685
RFC cleanup
Wollac Oct 20, 2021
74a46d1
Merge remote-tracking branch 'origin/master' into message
Wollac Oct 20, 2021
b687e55
use correct links
Wollac Oct 20, 2021
2e2ef6f
use correct folder
Wollac Oct 20, 2021
92cc7ef
Add missing data length integer
Wollac Oct 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions text/0017-message/0017-message.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
+ Feature name: `tangle-message`
+ Start date: 2020-07-28
+ RFC PR: [iotaledger/protocol-rfcs#0017](https://github.com/iotaledger/protocol-rfcs/pull/0017)

# Summary

A message is the object nodes gossip around in the network. It always references two other messages that are known as _parents_. It is stored as a vertex on the tangle data structure that the nodes maintain.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It always references two other messages that are known as parents.

Not factually correct

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good catch. I'll go over the entire text and make sure that everything is correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thibault-martinez I did a mayor rewrite of the RFC that should hopefully address all the outstanding issues. Please consider reviewing again.


The messages contain payloads. Some of them will be core payloads that will be processed by all nodes as part of the core protocol. Some of them will be community payloads that will enable the building of new functionalities on top of the Tangle. Some payloads may have other nested payloads embedded inside.
So upon parsing, it is done layer by layer.

# Motivation

To better understand this layered design, consider the internet protocol, for example: there is an Ethernet frame that contains an IP payload. This in turn contains a TCP packet that encapsulates an HTTP payload. Each layer has a certain responsibility and once this responsibility is completed, we move on to the next layer.

The same is true with how messages are parsed. The outer layer of the message enables the mapping of the message to a vertex in the Tangle and performing some basic validation. The next layer may be a transaction that mutates the ledger state, and the next layer may provide some extra functionality on the transactions to be used by applications.

By making it possible to add and exchange payloads, an architecture is being created that can be easily extended to accommodate future needs.

# Detailed design

### Data types

The following are data types that we will use when we specify fields in the message and payloads.

| Name | Description |
| ------ | ------------- |
| uint8 | An unsigned 8 bit integer encoded in Little Endian. |
| uint16 | An unsigned 16 bit integer encoded in Little Endian. |
| uint32 | An unsigned 32 bit integer encoded in Little Endian. |
| uint64 | An unsigned 64 bit integer encoded in Little Endian. |
| ByteArray[N] | A static size array of size N. |
| ByteArray | A dynamically sized array. A uint32 denotes its length. |
| string | A dynamically sized array of an UTF-8 encoded string. A uint16 denotes its length. |


### Message ID
The message ID will be the [BLAKE2b-256](https://tools.ietf.org/html/rfc7693) hash of the byte contents of the message. It should be used by the nodes to index the messages and by external APIs.


### Message structure

<table>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td>NetworkID</td>
<td>uint64</td>
<td>Network identifier. This field will signify whether this message was meant for mainnet, testnet, or a private net. It also tells what protocol rules apply to the message. It is first 8 bytes of the BLAKE2b-256 hash of the concatenation of the network type and the protocol version string.</td>
</tr>
<tr>
<td> Parents Count </td>
<td> uint8</td>
<td> The number of messages we directly approve. Can be any value between 1-8.</td>
Wollac marked this conversation as resolved.
Show resolved Hide resolved
</tr>
<tr>
<td>Parents </td>
<td>ByteArray[32 * Parents Count]</td>
<td>The Message IDs that are referenced.</td>
Wollac marked this conversation as resolved.
Show resolved Hide resolved
</tr>
<tr>
<td>Payload Length</td>
GalRogozinski marked this conversation as resolved.
Show resolved Hide resolved
<td>uint32</td>
<td> The length of the Payload. Since its type may be unknown to the node it must be declared in advanced. 0 length means no payload will be attached.</td>
</tr>
<tr>
<td colspan="1">
Payload
</td>
<td colspan="2">
<details open="true">
<summary>Generic Payload</summary>
<blockquote>
An outline of a general payload
</blockquote>
<table>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td>Payload Type</td>
<td>uint32</td>
<td>
The type of the payload. It will instruct the node how to parse the fields that follow.
</td>
</tr>
<tr>
<td>Data Fields</td>
<td>ANY</td>
<td>A sequence of fields, where the structure depends on <code>Payload Type</code>.</td>
</tr>
</table>
</details>
<tr>
<td>Nonce</td>
<td>uint64</td>
<td>The nonce which lets this message fulfill the Proof-of-Work requirement.</td>
</tr>
</table>

### Message validation

A message is considered valid, if the following syntactic rules are met:

1. The message size must not exceed 32 KiB (32 * 1024 bytes).
2. When parsing the message is complete, there must not be any trailing bytes left that were not parsed.
3. The optional `Payload Type` is known to the node.
4. The message PoW score (as described in [RFC-0024](https://github.com/iotaledger/protocol-rfcs/blob/master/text/0024-message-pow/0024-message-pow.md)) is not less than the configured threshold.
5. The `Parents Count` is between 1 and 8.


### Payloads

While messages without a payload, i.e. `Payload Length` set to zero, are valid, such messages do not contain any information. As such, messages usually contain a payload. The specification of the payloads is out of scope of this RFC. Below is a table of the currently specified core payloads with a link to their specifications. The _indexation payload_ will be specified here as an example:
| Payload Name | Type Value | RFC |
| ------------ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Transaction | 0 | [RFC-0018 (draft)](https://github.com/luca-moser/protocol-rfcs/blob/signed-tx-payload/text/0000-signed-transaction-payload/0000-signed-transaction-payload.md) |
| Milestone | 1 | [RFC-0019 (draft)](https://github.com/jakubcech/protocol-rfcs/blob/jakubcech-milestonepayload/text/0019-milestone-payload/0019-milestone-payload.md) |
| Indexation | 2 | [RFC-0017](#indexation-payload) |

### Indexation payload

To be clear, the concept of the Payload allows the addition of an index to the encapsulating message, as well as some arbitrary data. Nodes will expose an API that will enable the querying of messages by the index.
Adding those capabilities may open nodes to DOS attack vectors:
1. Proliferation of index keys that may blow up the node's DB
2. Proliferation of messages associated with the same index

Node implementations may provide weak guarantees regarding the completion of indexes to address the above scenarios.

Besides the index, the payload will also have a data field.
A message that has been attached to the Tangle and approved by a milestone has several useful properties: verifying that the content of the data did not change and determining the approximate time it was published by checking the approving milestone. If the payload will be incorporated under
the signed _transaction payload_, the content will be signed as well.


The structure of the payload is simple:

| Name | Type | Description |
| -------- | ----------- | ----------- |
| Payload Type | uint32 | Must be set to **2** |
| Index | ByteArray | The index key of the message |
Wollac marked this conversation as resolved.
Show resolved Hide resolved
| Data | ByteArray | Data we are attaching |

Note that `Index` field should be 1 to 64 bytes long for the payload to be valid. The `Data` may have a length of 0.

Wollac marked this conversation as resolved.
Show resolved Hide resolved

### Serialization Example

Below is a serialized valid message with the indexation payload. The index is the "SPAM" ASCII string and the message is the "Hello Iota"
ASCII string. The message PoW Hash would have 10 trailing zeroes for the given nonce in this example. Bytes are expressed as hexadecimal numbers.

[Version] **`01`** [Parent 1] `F532A53545103276B46876C473846D98648EE418468BCE76DF4868648DD73E5D` [Parent 2] `78D546B46AEC4557872139A48F66BC567687E8413578A14323548732358914A2` [Payload Length]
*`1100000000000000000000000000000000000000000000000000000000000000`*[Payload Type]**`02`**[Index] *`04`*`5350414D` [Data]*`0A`*`48656C6C6F20496F7461`[Nonce]`5d38333333333333`

Wollac marked this conversation as resolved.
Show resolved Hide resolved
# Rationale and alternatives

Instead of creating a layered approach, we could have simply created a flat transaction message that is tailored for mutating the ledger state, and try to fit all the use cases there. For example, with the unsigned data use-case, we could have filled some section of the transaction with the data. Then via a flag in the transaction, we could have instructed to not pass this transaction to the service that attempts to mutate the ledger state.

This approach seems less extensible. It might have made sense if we wanted to build a protocol that is just for ledger mutating transactions, but we want to be able to extend the protocol to do more than that.