Skip to main content

Summary

This TIP proposes a UTXO-based transaction structure consisting of all the inputs and outputs of a transfer. Specifically, this TIP defines a transaction payload for blocks described in TIP-24 and extends the transaction payload described in TIP-7.

Motivation

TIP-7 describes the introduction of the UTXO ledger model for Chrysalis. This TIP extends the transaction model of the UTXO ledger to:

  • accommodate for the new output types introduced in TIP-18,
  • include a Network ID field in the transaction for replay protection,
  • introduce Inputs Commitment field to prevent client eclipse attacks that would result in loss of funds,
  • relax syntactic validation rules such that inputs and outputs of a transaction are no longer lexicographically ordered, furthermore outputs do not have to be unique.

The motivation for such changes is to provide a more flexible and secure framework for wallets and layer 2 applications. Chrysalis focused solely on using the ledger as a payment application, while Stardust transforms the ledger into a settlement layer for interconnected layer 2 blockchains and applications.

Detailed design

UTXO

The unspent transaction output (UTXO) model defines a ledger state where balances are not directly associated to addresses but to the outputs of transactions. In this model, transactions reference outputs of previous transactions as inputs, which are consumed (removed) to create new outputs. A transaction must consume all the funds of the referenced inputs.

Using a UTXO-based model provides several benefits:

  • Parallel validation of transactions.
  • Easier double-spend detection, since conflicting transactions would reference the same UTXO.
  • Replay-protection which is important when having reusable addresses. Replaying the same transaction would manifest itself as already being applied or existent and thus not have any impact.
  • Balances are no longer strictly associated to addresses. This allows a higher level of abstraction and thus enables other types of outputs with particular unlock criteria.

Within a transaction using UTXOs, inputs and outputs make up the to-be-signed data of the transaction. The section unlocking the inputs is called the unlock. An unlock may contain a signature proving ownership of a given input's address and/or other unlock criteria.

The following image depicts the flow of funds using UTXO:

UTXO flow

Structure

Serialized layout

A Transaction Payload is made up of two parts:

  1. The Transaction Essence part which contains the inputs, outputs and an optional embedded payload.
  2. The Unlocks which unlock the inputs of the Transaction Essence.

The serialized form of the transaction is deterministic, meaning the same logical transaction always results in the same serialized byte sequence. However, in contrast to Chrysalis Phase 2 TIP-7 the inputs and outputs are considered as lists. They can contain duplicates and their serialization order matches the order of the list; they do not need to be sorted.

The Transaction Payload ID is the BLAKE2b-256 hash of the entire serialized payload data including unlocks.

The following table describes the entirety of a Transaction Payload in its serialized form following the notation from TIP-21:

NameTypeDescription
Payload Typeuint32Set to value 6 to denote a TIP-20 Transaction Payload.
Essence oneOf
Transaction Essence
Describes the essence data making up a transaction by defining its inputs, outputs and an optional payload.
NameTypeDescription
Transaction Typeuint8Set to value 1 to denote a TIP-20 Transaction Essence.
Network IDuint64The unique value denoting whether the block was meant for mainnet, shimmer, testnet, or a private network. It consists of the first 8 bytes of the BLAKE2b-256 hash of the network name.
Inputs Countuint16The number of input entries.
Inputs anyOf
UTXO Input
Describes an input which references an unspent transaction output to consume.
NameTypeDescription
Input Typeuint8Set to value 0 to denote an TIP-20 UTXO Input.
Transaction IDByteArray[32]The BLAKE2b-256 hash of the transaction payload containing the referenced output.
Transaction Output Indexuint16The output index of the referenced output.
Inputs CommitmentByteArray[32]BLAKE2b-256 hash serving as a commitment to the serialized outputs referenced by Inputs.
Outputs Countuint16The number of output entries.
Outputs anyOf
Basic Output
Describes a deposit to a single address. The output might contain optional features and native tokens.
Alias Output
Describes an alias account in the ledger.
Foundry Output
Describes a foundry that controls supply of native tokens.
NFT Output
Describes a unique, non-fungible token deposit to a single address.
Payload Lengthuint32The length in bytes of the optional payload.
Payload optOneOf
Tagged Data Payload
Describes data with optional tag, defined in TIP-23.
Unlocks Countuint16The number of unlock entries. It must match the field Inputs Count.
Unlocks anyOf
Signature Unlock
Defines an unlock containing a signature.
Reference Unlock
References a previous unlock, where the same unlock can be used for multiple inputs.
Alias Unlock
References a previous unlock of a consumed alias output.
NFT Unlock
References a previous unlock of a consumed NFT output.

Transaction Essence

The Transaction Essence of a Transaction Payload carries the inputs, outputs, and an optional payload. The Transaction Essence is an explicit type and therefore starts with its own Transaction Essence Type byte which is of value 1 for TIP-20 Transaction Essence.

Network ID

The Network ID field of the transaction essence serves as a replay protection mechanism. It is a unique value denoting whether the transaction was meant for the IOTA mainnet, shimmer, testnet-1, or a private network. It consists of the first 8 bytes of the BLAKE2b-256 hash of the Network Name protocol parameter, interpreted as an unsigned integer number.

Network NameResulting Network IDNetwork Name defined in
iota-mainnet9374574019616453254TIP-22
shimmer14364762045254553490TIP-32
testnet-11856588631910923207-
example-mynetwork1967754805504104511-

Inputs

The Inputs field holds the inputs to consume in order to fund the outputs of the Transaction Payload. Currently, there is only one type of input, the UTXO Input. In the future, more types of inputs may be specified as part of protocol upgrades.

Each input must be accompanied by a corresponding Unlock at the same index in the Unlocks part of the Transaction Payload.

UTXO Input

A UTXO Input is an input which references an unspent output of a previous transaction. This UTXO is uniquely identified by its Output ID, defined by the Transaction ID of the creating transaction together with corresponding output index. Each UTXO Input must be accompanied by an Unlock that is allowed to unlock the referenced output.

Inputs Commitment

The Inputs Commitment field of the Transaction Essence is a cryptographic commitment to the content of the consumed outputs (inputs). It consists of the BLAKE2b-256 hash of the concatenated output hashes.

In the Inputs field, they are only referenced by Output ID. While the Output ID technically depends on the content of the actual output, a client has no way of validating this without access to the original transaction. For the Inputs Commitment, the client has to be aware of the outputs’ content in order to produce a semantically valid transaction. This protects clients against eclipse attacks that would result in loss of funds.

Outputs

The Outputs field holds the outputs that are created by the Transaction Payload. There are different output types, but they must all have an Amount field denoting the number of IOTA coins to deposit.

The following table lists all the output types that are currently supported as well as links to the corresponding specification. The SigLockedSingleOutput as well as the SigLockedDustAllowanceOutput introduced in Chrysalis Phase 2 TIP-7 have been removed and are no longer supported.

Output NameType ValueTIP
Basic3TIP-18
Alias4TIP-18
Foundry5TIP-18
NFT6TIP-18

Payload

The Transaction Essence itself can contain another payload as described in general in TIP-24. The semantic validity of the encapsulating Transaction Payload does not have any impact on the payload.

The following table lists all the payload types that can be nested inside a Transaction Essence as well as links to the corresponding specification:

NameType ValueTIP
Tagged Data5TIP-23

Unlocks

The Unlocks field holds the unlocks unlocking inputs within a Transaction Essence.

The following table lists all the output types that are currently supported as well as links to the corresponding specification. The Signature Unlock and the Reference Unlock are specified as part of this TIP.

Unlock NameType ValueTIP
Signature0TIP-20
Reference1TIP-20
Alias2TIP-18
NFT3TIP-18

Signature Unlock

The Signature Unlock defines an Unlock which holds a signature signing the BLAKE2b-256 hash of the Transaction Essence (including the optional payload). It is serialized as follows:

NameTypeDescription
Unlock Typeuint8Set to value 0 to denote a Signature Unlock.
Signature oneOf
Ed25519 Signature
NameTypeDescription
Signature Typeuint8Set to value 0 to denote an Ed25519 Signature.
Public keyByteArray[32]The Ed25519 public key of the signature.
SignatureByteArray[64]The Ed25519 signature signing the Blake2b-256 hash of the serialized Transaction Essence.
Unlock syntactic validation
  • Signature must contain an Ed25519 Signature.
  • The Signature Unlock must be unique, i.e. there must not be any other Signature Unlocks in the Unlocks field of the transaction payload with the same signature.

Reference Unlock

The Reference Unlock defines an Unlock which references a previous Unlock (which must not be another Reference Unlock). It must be used if multiple inputs can be unlocked via the same Unlock. It is serialized as follows:

NameTypeDescription
Unlock Typeuint8Set to value 1 to denote a Reference Unlock.
Referenceuint16Represents the index of a previous unlock.
Unlock syntactic validation
  • The Reference Unlock at index i must have Reference < i and the unlock at index Reference must be a Signature Unlock.

Example: Consider a Transaction Essence containing the UTXO Inputs 0, 1 and 2, where 0 and 2 are both spending outputs belonging to the same Ed25519 address A and 1 is spending from a different address B. This results in the following structure of the Unlocks part:

IndexUnlock
0A Signature Unlock holding the Ed25519 signature for address A.
1A Signature Unlock holding the Ed25519 signature for address B.
2A Reference Unlock which references 0, as both require the same signature for A.

Validation

A Transaction Payload has different validation stages, since some validation steps can only be executed when certain information has (or has not) been received. We therefore distinguish between syntactic and semantic validation.

The different output types and optional output features introduced by TIP-18 add additional constraints to the transaction validation rules, but since these are specific to the given outputs and features, they are discussed for each output type and feature type separately.

Syntactic validation

Syntactic validation is checked as soon as the transaction has been received. It validates the structure but not the signatures of the transaction. If the transaction does not pass this stage, it must not be broadcast further and can be discarded right away.

The following criteria defines whether a payload passes the syntactical validation:

  • Essence:
    • Transaction Type value must denote a TIP-20 Transaction Essence.
    • Network ID must match the value of the current network.
    • Inputs:
      • Inputs Count must be 0 < x ≤ Max Inputs Count.
      • For each input the following must be true:
        • Input Type must denote a UTXO Input.
        • Transaction Output Index must be 0 ≤ x < Max Outputs Count.
      • Each pair of Transaction ID and Transaction Output Index must be unique in the list of inputs.
    • Outputs:
      • Outputs Count must be 0 < x ≤ Max Outputs Count.
      • For each output the following must be true:
        • Output Type must match one of the values described under Outputs.
        • The output itself must pass syntactic validation.
      • The sum of all Amount fields must not exceed Max IOTA Supply.
      • The count of all distinct native tokens present in outputs must not be larger than Max Native Token Count.
    • Payload (if present):
      • Payload Type must match one of the values described under Payload.
      • Payload fields must be correctly parsable in the context of the Payload Type.
      • The payload itself must pass syntactic validation.
  • Unlocks:
    • Unlocks Count must match Inputs Count of the Transaction Essence.
    • For each unlock the following must be true:
      • Each Unlock Type must match one of the values described under Unlocks.
      • The unlock itself must pass syntactic validation.
  • Given the type and length information, the Transaction Payload must consume the entire byte array of the Payload field of the encapsulating object.

Semantic validation

The Semantic validation of a Transaction Payload is performed when its encapsulating block is confirmed by a milestone. The semantic validity of transactions depends on the order in which they are processed. Thus, it is necessary that all the nodes in the network perform the checks in the same order, no matter the order in which the transactions are received. This is assured by using the White-Flag ordering as described in TIP-2.

Processing transactions according to the White-Flag ordering enables users to spend UTXOs which are created in the same milestone confirmation cone, as long as the spending transaction comes after the funding transaction in the aforementioned White-Flag order. In this case, it is recommended that users include the Block ID of the funding transaction as a parent of the block containing the spending transaction.

The following criteria defines whether a payload passes the semantic validation:

  • Each input must reference a valid UTXO, i.e. the output referenced by the input's Transaction ID and Transaction Output Index is known (booked) and unspent.
  • Inputs Commitment must equal BLAKE2( BLAKE2(O1) || … || BLAKE2(On) ), where O1, ..., On are the complete serialized outputs referenced by the Inputs field in that order.
  • The transaction must spend the entire coin balance, i.e. the sum of the Amount fields of all the UTXOs referenced by inputs must match the sum of the Amount fields of all outputs.
  • The count of all distinct native tokens present in the UTXOs referenced by inputs and in the transaction outputs must not be larger than Max Native Token Count. A native token that occurs several times in both inputs and outputs is counted as one.
  • The transaction is balanced in terms of native tokens, when the amount of native tokens present in all the UTXOs referenced by inputs equals to that of outputs. When the transaction is imbalanced, it must hold true that when there is a surplus of native tokens on the:
    • output side of the transaction: the foundry outputs controlling outstanding native token balances must be present in the transaction. The validation of the foundry output(s) determines if the minting operations are valid.
    • input side of the transaction: the transaction destroys tokens. The presence and validation of the foundry outputs of the native tokens determines whether the tokens are burned (removed from the ledger) or melted within the foundry. When the foundry output is not present in the transaction, outstanding token balances must be burned.
  • Each output and all its output features must pass semantic validation in the context of the following input:
    1. The Transaction Payload,
    2. the list of UTXOs referenced by inputs and
    3. the Unix timestamp of the confirming milestone.
  • Each unlock must be valid with respect to the UTXO referenced by the input of the same index:
    • If it is a Signature Unlock:
      • The Signature Type must match the Address Type of the UTXO,
      • the BLAKE2b-256 hash of Public Key must match the Address of the UTXO and
      • the Signature field must contain a valid signature for Public Key.
    • If it is a Reference Unlock, the referenced Signature Unlock must be valid with respect to the UTXO.
    • If it is an Alias Unlock:
      • The address unlocking the UTXO must be an Alias Address.
      • The referenced Unlock unlocks the alias defined by the unlocking address of the UTXO.
    • If it is an NFT Unlock:
      • The address unlocking the UTXO must be a NFT Address.
      • The referenced Unlock unlocks the NFT defined by the unlocking address of the UTXO.

If a Transaction Payload passes the semantic validation, its referenced UTXOs must be marked as spent and its new outputs must be created/booked in the ledger. The Block ID of the block encapsulating the processed payload then also becomes part of the input for the White-Flag Merkle tree hash of the confirming milestone (TIP-4).

Transactions that do not pass semantic validation are ignored. Their UTXOs are not marked as spent and their outputs are not booked in the ledger.

Miscellaneous

Transaction timestamps

Since transaction timestamps – whether they are signed or not – do not provide any guarantee of correctness, they have been left out of the Transaction Payload. Instead, the global timestamp of the confirming milestone (TIP-8) is used.

Address reuse

While, in contrast to Winternitz one-time signatures (W-OTS), producing multiple Ed25519 signatures for the same private key and address does not decrease its security, it still drastically reduces the privacy of users. It is thus considered best practice that applications and services create a new address per deposit to circumvent these privacy issues.

In essence, Ed25519 support allows for smaller transaction sizes and to safely spend funds which were sent to an already used deposit address. Ed25519 addresses are not meant to be used like email addresses. See this Bitcoin wiki article for further information.

Drawbacks

  • The new transaction format is the core data type within the IOTA ecosystem. Changing it means that all projects need to accommodate it, including wallets, web services, client libraries and applications using IOTA in general. It is not possible to keep these changes backwards compatible, meaning that all nodes must upgrade to further participate in the network.
  • It is not possible to produce a valid transaction without having access to the content of the consumed outputs.

Rationale and alternatives

  • Inputs Commitment and Network ID are both explicit fields of the transaction, while they could be made configuration parameters for the signature generating process. In this scenario the signature would be invalid if the parameters on client and network side mismatch. While this would reduce the size of a transaction, it would make it impossible to debug the reason for having an invalid signature and transaction. With the current solution we intend to optimize for ease of development.
  • Uniqueness of all inputs is kept as it prevents introducing double spends in the same transaction.

Copyright

Copyright and related rights waived via CC0.