-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TIP-24 Tangle Block (Stardust) (#55)
* add tip-24 * Update tip-0024.md * Apply suggestions from code review Co-authored-by: Levente Pap <[email protected]> * Update tip-0024.md * Remove NetworkId, add Protocol Version * Add length to Protocol Version in example * Update TX Payload Reference (#23) * Use updated Milestone payload type * Fix payload keyword `optOneOf` * Clarify handling of invalid messages * Rename "Message" to "Block" to align with IOTA 2.0 terminology * Describe payload-based PoW validation * Update tips/TIP-0024/tip-0024.md Co-authored-by: Thibault Martinez <[email protected]> * PR review suggestions Co-authored-by: Levente Pap <[email protected]> Co-authored-by: Thibault Martinez <[email protected]>
- Loading branch information
1 parent
d90b8fc
commit fd388c0
Showing
1 changed file
with
179 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,179 @@ | ||
--- | ||
tip: 24 | ||
title: Tangle Block | ||
description: Generalization of the Tangle transaction concept | ||
author: Wolfgang Welz (@Wollac) <[email protected]> | ||
discussions-to: https://github.com/iotaledger/tips/pull/55 | ||
status: Draft | ||
type: Standards | ||
layer: Core | ||
replaces: 6 | ||
created: 2022-01-24 | ||
--- | ||
|
||
# Abstract | ||
|
||
The Tangle is the graph data structure behind IOTA. In the legacy IOTA protocol, the vertices of the Tangle are represented by transactions. This document proposes an abstraction of this idea where the vertices are generalized *blocks*, which then contain the transactions or other structures that are processed by the IOTA protocol. Just as before, each block directly approves other blocks, which are known as _parents_. | ||
|
||
The blocks 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. | ||
|
||
# Motivation | ||
|
||
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 blocks are parsed. The outer layer of the block enables the mapping of the block to a vertex in the Tangle and allows 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. | ||
|
||
# Specification | ||
|
||
## Block ID | ||
|
||
The *Block ID* is the [BLAKE2b-256](https://tools.ietf.org/html/rfc7693) hash of the entire serialized block. | ||
|
||
## Serialized Layout | ||
|
||
The following table describes the serialization of a _Block_ following the notation from [TIP-21](../TIP-0021/tip-0021.md): | ||
|
||
<table> | ||
<tr> | ||
<th>Name</th> | ||
<th>Type</th> | ||
<th>Description</th> | ||
</tr> | ||
<tr> | ||
<td>Protocol Version</td> | ||
<td>uint8</td> | ||
<td> Protocol version number of the block.</td> | ||
</tr> | ||
<tr> | ||
<td>Parents Count</td> | ||
<td>uint8</td> | ||
<td>The number of blocks that are directly approved.</td> | ||
</tr> | ||
<tr> | ||
<td valign="top">Parents <code>anyOf</code></td> | ||
<td colspan="2"> | ||
<details> | ||
<summary>Parent</summary> | ||
<blockquote> | ||
References another directly approved block. | ||
</blockquote> | ||
<table> | ||
<tr> | ||
<th>Name</th> | ||
<th>Type</th> | ||
<th>Description</th> | ||
</tr> | ||
<tr> | ||
<td>Block ID</td> | ||
<td>ByteArray[32]</td> | ||
<td>The Block ID of the parent.</td> | ||
</tr> | ||
</table> | ||
</details> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>Payload Length</td> | ||
<td>uint32</td> | ||
<td>The length of the following payload in bytes. A length of 0 means no payload will be attached.</td> | ||
</tr> | ||
<tr> | ||
<td valign="top">Payload <code>optOneOf</code></td> | ||
<td colspan="2"> | ||
<details open="true"> | ||
<summary>Generic Payload</summary> | ||
<blockquote> | ||
An outline of a generic 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 block fulfill the PoW requirement.</td> | ||
</tr> | ||
</table> | ||
|
||
## Syntactic validation | ||
|
||
The Tangle can only contain syntactically valid blocks. Invalid blocks must be rejected by the node. | ||
The following criteria defines whether the block passes the syntactic validation: | ||
|
||
- The total length of the serialized block must not exceed `Max Block Length`. | ||
- `Protocol Version` must match the `Protocol Version` config parameter of the node. | ||
- Parents: | ||
- `Parents Count` must be at least 1 and not larger than `Max Parents Count`. | ||
- `Parents` must be sorted in lexicographical order. | ||
- Each `Block ID` must be unique. | ||
- Payload (if present): | ||
- `Payload Type` must match one of the values described under [Payloads](#payloads). | ||
- `Data Fields` must be correctly parsable in the context of the `Payload Type`. | ||
- The payload itself must pass syntactic validation. | ||
- `Nonce` must be valid with respect to the PoW condition described under [Payloads](#payloads). The PoW score itself is computed according to [TIP-12](../TIP-0012/tip-0012.md). | ||
- There must be no trailing bytes after all block fields have been parsed. | ||
|
||
### PoW validation | ||
|
||
The PoW that needs to be performed for each block protects the network against denial-of-service attacks where in a short time too many blocks are issued for the nodes to process. As the processing time of a block heavily depends on the contained payload, the PoW check can also depend on the `Payload Type` and is described under [Payloads](#payloads). | ||
It is important to note, that the actual parsing and validating of a payload can be computationally expensive. Thus, it is recommended to first parse the block with all its fields including `Payload Type` (but not parsing or validating the actual payload `Data Fields`). Now, simple syntactic validation steps – including PoW validation – can be performed and invalid blocks already filtered out before the payload is validated. With this approach, payload-based PoW validation is not significantly more expensive than payload-agnostic validation. | ||
|
||
## Payloads | ||
|
||
While blocks without a payload, i.e. `Payload Length` set to zero, are valid, such blocks do not contain any information. As such, blocks usually contain a payload. The detailed specification of each payload type is out of scope of this TIP. The following table lists all currently specified payloads that can be part of a block and links to their specification: | ||
|
||
| Payload Name | Type Value | TIP | PoW Condition | | ||
|--------------|------------|-----------------------------------|--------------------------------| | ||
| No Payload | - | - | PoW score ≥ `Min PoW Score` | | ||
| Tagged Data | 5 | [TIP-23](../TIP-0023/tip-0023.md) | PoW score ≥ `Min PoW Score` | | ||
| Transaction | 6 | [TIP-20](../TIP-0020/tip-0020.md) | PoW score ≥ `Min PoW Score` | | ||
| Milestone | 7 | [TIP-29](../TIP-0029/tip-0029.md) | `nonce` = `0x0000000000000000` | | ||
|
||
## Example | ||
|
||
Below is the full serialization of a valid block with a _Tagged Data Payload_. The tag is the "IOTA" ASCII string and the data is the "hello world" ASCII string. Bytes are expressed as hexadecimal numbers. | ||
|
||
- Protocol Version (1-byte): `02` (2) | ||
- Parents Count (1-byte): `02` (2) | ||
- Parents (64-byte): | ||
- `210fc7bb818639ac48a4c6afa2f1581a8b9525e20fda68927f2b2ff836f73578` | ||
- `db0fa54c29f7fd928d92ca43f193dee47f591549f597a811c8fa67ab031ebd9c` | ||
- Payload Length (4-byte): `18000000` (24) | ||
- Payload (24-byte): | ||
- Payload Type (4-byte): `05000000` (5) | ||
- Tag (5-byte): | ||
- Length (1-byte): `04` (4) | ||
- Tag (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 block that is tailored to mutate the ledger state, and try to fit all the use cases there. For example, with the tagged 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 | ||
|
||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |