Skip to main content

Tangle Message


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.

Detailed design


Message ID

The Message ID is the BLAKE2b-256 hash of the entire serialized message.

Serialized layout

The following table describes the serialization of a Message following the notation from RFC-0041:

Network IDuint64Network 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 Countuint8The number of messages that are directly approved.
Parents anyOf
References another directly approved message.
Message IDByteArray[32]The Message ID of the parent.
Payload Lengthuint32The length of the following payload in bytes. A length of 0 means no payload will be attached.
Payload oneOf
Generic Payload
An outline of a generic payload
Payload Typeuint32The type of the payload. It will instruct the node how to parse the fields that follow.
Data FieldsANYA sequence of fields, where the structure depends on Payload Type.
Nonceuint64The nonce which lets this message fulfill the PoW requirement.

Message validation

The following criteria defines whether the message passes the syntactical validation:

  • The total message size must not exceed 32 KiB (32 * 1024 bytes).
  • Parents:
    • Parents Count must be at least 1 and not larger than 8.
    • Parents must be sorted in lexicographical order.
    • Each Message ID must be unique.
  • Payload (if present):
    • Payload Type must match one of the values described under Payloads.
    • Data fields must be correctly parsable in the context of the Payload Type.
    • The payload itself must pass syntactic validation.
  • Nonce must 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 NameType ValueTIP

Indexation payload

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 Typeuint32Set to value 2 to denote an Indexation Payload.
Index Lengthuint16The length of the following index field in bytes.
IndexByteArray[Index Length]The index key of the message
DataByteArrayBinary data.

Note that 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): 0000000000000000 (0)
  • Parents Count (1-byte): 02 (2)
  • Parents (64-byte):
    • 210fc7bb818639ac48a4c6afa2f1581a8b9525e20fda68927f2b2ff836f73578
    • db0fa54c29f7fd928d92ca43f193dee47f591549f597a811c8fa67ab031ebd9c
  • Payload Length (4-byte): 19000000 (25)
  • Payload (25-byte):
    • Payload Type (4-byte): 02000000 (2)
    • Index Length (2-byte): 0400 (4)
    • Index (4-byte): 494f5441 ("IOTA")
    • Data (15-byte):
      • Length (4-byte): 0b000000 (11)
      • Data (11-byte): 68656c6c6f20776f726c64 ("hello world")
  • Nonce (8-byte): ce6d000000000000 (28110)

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.