- (iotaledger/tips#0037) Fixed internal links
The Tangle is the graph data structure behind IOTA. In the current IOTA protocol, the vertices of the Tangle are represented by transactions. This document proposes an abstraction of this idea where the vertices are generalized messages, which then contain the transactions or other structures that are processed by the IOTA protocol. Just as before, each message directly approves other messages, which are known as parents.
The messages can contain payloads. These are core payloads that will be processed by all nodes as part of the IOTA protocol. Some payloads may have other nested payloads embedded inside. Hence, parsing is done layer by layer.
To better understand this layered design, consider the Internet Protocol (IP), 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 allow us to perform some basic validation. The next layer may be a transaction that mutates the ledger state, and one layer further 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 easily be extended to accommodate future needs.
The Message ID is the BLAKE2b-256 hash of the entire serialized message.
The following table describes the serialization of a Message following the notation from RFC-0041:
|Network ID||uint64||Network identifier. This field denotes whether the message was meant for mainnet, testnet, or a private net. It also marks what protocol rules apply to the message. Usually, it will be set to the first 8 bytes of the BLAKE2b-256 hash of the concatenation of the network type and the protocol version string.|
|Parents Count||uint8||The number of messages that are directly approved.|
References another directly approved message.
|Payload Length||uint32||The length of the following payload in bytes. A length of 0 means no payload will be attached.|
An outline of a generic payload
|Nonce||uint64||The nonce which lets this message fulfill the PoW requirement.|
The following criteria defines whether the message passes the syntactical validation:
- The total message size must not exceed 32 KiB (32 * 1024 bytes).
Parents Countmust be at least 1 and not larger than 8.
Parentsmust be sorted in lexicographical order.
Message IDmust be unique.
- Payload (if present):
Payload Typemust match one of the values described under Payloads.
Data fieldsmust be correctly parsable in the context of the
- The payload itself must pass syntactic validation.
Noncemust be a valid solution of the message PoW as described in TIP-12.
- There must be no trailing bytes after all message fields have been parsed.
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 detailed specification of each payload type is out of scope of this RFC. The following table lists all currently specified payloads that can be part of a message and links to their specification. The indexation payload will be specified here as an example:
|Payload Name||Type Value||TIP|
This payload allows the addition of an index to the encapsulating message, as well as some arbitrary data. Nodes will expose an API that allows to query messages by index.
The structure of the indexation payload is as follows:
|Payload Type||uint32||Set to value 2 to denote an Indexation Payload.|
|Index Length||uint16||The length of the following index field in bytes.|
|Index||ByteArray[Index Length]||The index key of the message|
Index field must be at least 1 byte and not longer than 64 bytes for the payload to be valid. The
Data may have a length of 0.
Below is the full serialization of a valid message with an indexation payload. The index is the "IOTA" ASCII string and the data is the "hello world" ASCII string. Bytes are expressed as hexadecimal numbers.
- Network ID (8-byte):
- Parents Count (1-byte):
- Parents (64-byte):
- Payload Length (4-byte):
- Payload (25-byte):
- Payload Type (4-byte):
- Index Length (2-byte):
- Index (4-byte):
- Data (15-byte):
- Length (4-byte):
- Data (11-byte):
- Length (4-byte):
- Payload Type (4-byte):
- Nonce (8-byte):
Rationale and alternatives
Instead of creating a layered approach, we could have simply created a flat transaction message that is tailored to mutate the ledger state, and try to fit all the use cases there. For example, with the indexed data use case, we could have filled some section of the transaction with that particular data. Then, this transaction would not correspond to a ledger mutation but instead only carry data.
This approach seems less extensible. It might have made sense if we had 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.
Copyright and related rights waived via CC0.