Skip to content

Instantly share code, notes, and snippets.

@luca-moser
Created July 14, 2020 07:34
Show Gist options
  • Save luca-moser/1e3243c61c346252315a81d63c49d625 to your computer and use it in GitHub Desktop.
Save luca-moser/1e3243c61c346252315a81d63c49d625 to your computer and use it in GitHub Desktop.

Draft RFC: Signed Transaction Payload

Summary

This RFC defines a new transaction structure for Chrysalis Phase 2, which replaces the current notion of bundles. Specifically, this RFC describes the transaction payload to be embedded into a message.

Motivation

The current IOTA protocol uses so called transactions (which are vertices in the Tangle), where each transaction defines either an input or output. A grouping of those input/output transaction vertices make up a so called bundle which transfers the given values as an atomic unit (the entire bundle is applied or none of it). The input transactions define the funds to consume to create the deposits onto the output transactions target addresses. Additionally, to accommodate the rather big WOTS signatures, additional transaction vertices might be part of the bundle in order to carry parts of the signature which don't fit into one transaction vertex.

The bundle concept has proven to be tedious, spawning a plethora of problems:

  • Since the data making up the bundle is split across multiple vertices, it complicates the validation of the entire transfer. Instead of being able to immediately tell whether a bundle is valid or not, a node implementation must first collect all parts of the bundle before any actual validation can happen. This increases the complexity of the node implementation immensely.
  • Reattaching the tail transaction of a bundle causes the entire transfer to be reapplied.
  • TODO write more problems

To fix the problems mentioned above and creating a more flexible transaction structure, we want to achieve a self-contained transaction structure defining the data of the entire transfer as a payload to be embedded into a message.

The new transaction structure should fulfill following criteria:

  • Support for Ed25519 (and thus reusable addresses) and WOTS signatures.
  • Support for adding new types of signature schemes, addresses, inputs and outputs as part of protocol upgrades.
  • Self-contained as in being able to validate the transaction immediately after receiving it.
  • Enable unspent transaction outputs (UTXO) as inputs instead of an account based model. (UTXO enables easier double-spend detection)

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 specify the outputs of previous transactions as inputs, which are consumed in order to create new outputs. A transaction must consume the entirety of the specified inputs.

Using an 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 especially important when having reusable addresses. Replaying the same transaction would manifest itself as already being applied or existent and thus not have any impact.
  • Technically seen, balances are no longer associated to addresses which raises the level of abstraction and thus enables other types of outputs. Consider for example a type of output which specifies the balance to be unlocked by a transaction using this output which must fulfill a very hard Proof-of-Work difficulty or supply some other unlock criteria etc.

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 unlock block. An unlock block 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

The way UTXOs are referenced is further described in the Structure section of this RFC.

Structure

Serialized Layout

A Signed Transaction payload is made up of two parts:

  1. The Unsigned Transaction part which contains the inputs, outputs and an optional embedded payload.
  2. The Unlock Blocks which unlock the Unsigned Transaction's inputs. In case the unlock block contains a signature, it signs the entire Unsigned Transaction part.

Following table structure describes the entirety of a Signed Transaction payload's serialized form:

Data Types
Notation Size Description
byte 1 byte An unsigned 8-bit integer.
varint variable A numerical value using N amount of bytes needed to represent its value. See docs on the Protocol Buffers site.
ByteArray 1 varint (length) + L * bytes A variable sized array of bytes where the leading varint L denotes the size of the array.
ByteArray[N] N * bytes A fixed sized array of bytes (without a leading varint N denoting the size of the array).
i.e. ByteArray[32]: A byte array with 32 bytes.
Subschema Notation
Name Description
oneOf One of the listed subschemas.
optOneOf Optionally one of the listed subschemas.
anyOf Any (one or more) of the listed subschemas.

Name Type Description
Payload Type varint Set to value 0 to denote a Signed Transaction payload.
Transaction oneOf
Unsigned Transaction
Describes the essence data making up a transaction by defining its inputs and outputs and an optional payload.
Name Type Description
Transaction Type byte/varint Set to value 0 to denote an Unsigned Transaction.
Inputs Count byte/varint The amount of inputs proceeding.
Inputs anyOf
UTXO Input
Describes an input which references an unspent transaction output to consume.
Name Type Description
Input Type byte/varint Set to value 0 to denote a UTXO Input.
Transaction ID ByteArray[32] The BLAKE2b-256 hash of the transaction from which the UTXO comes from.
Transaction Output Index byte/varint The index of the output on the referenced transaction to consume.
Unlock Index byte/varint The index of the unlock block unlocking the funds used in this input. Multiple inputs can reference the same unlock block, for example, inputs consuming multiple UTXOs residing on a specific Ed25519 address may reference the same signature unlock block with the corresponding signature unlocking the funds.
Unlock Mode byte/varint Defines the unlock block's type which unlocks this input.
Name Value Description
SIGNATURE 0 A signature unlock block unlocks this input.
Outputs Count byte/varint The amount of outputs proceeding.
Outputs anyOf
SigLockedSingleDeposit
Describes a deposit to a single address which is unlocked via a signature.
Name Type Description
Output Type byte/varint Set to value 0 to denote a SigLockedSingleDeposit.
Address oneOf
Ed25519 Address
Name Type Description
Address Type byte/varint Set to value 0 to denote an Ed25519 Address.
Address ByteArray[32] The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
WOTS Address
Name Type Description
Address Type byte/varint Set to value 1 to denote a WOTS Address.
Address ByteArray[49] The T5B1 encoded WOTS address.
Amount uint64 The amount of tokens to deposit with this SigLockedSingleDeposit output.
Payload Length byte/varint The length in bytes of the optional payload.
Payload optOneOf
Indexation Payload
Describes a payload which is used to instruct the node to index the Message of which it is part of.
Name Type Description
Payload Type byte/varint Set to value 4 to denote an Indexation payload.
Tag ByteArray[16] The tag which is used to index the Signed Transaction's hash.
Unlock Blocks Count byte/varint The count of unlock blocks proceeding.
Unlock Blocks anyOf
Ed25519 Signature Unlock Block
Name Type Description
Signature Type byte/varint Set to value 0 to denote an Ed25519 Signature Unlock Block.
Public key ByteArray[32] The public key of the Ed25519 keypair which is used to verify the signature.
Signature ByteArray[64] The signature signing the serialized Unsigned Transaction.
WOTS Signature Unlock Block
Name Type Description
Signature Type byte/varint Set to value 1 to denote a WOTS Signature Unlock Block.
Signature ByteArray The signature signing the serialized Unsigned Transaction.

Transaction Parts

In general, all parts of a Signed Transaction begin with a byte describing the type of the given part in order to keep the flexibility to introduce new types/versions of the given part in the future.

Unsigned Transaction / Essence Data

As described, the Unsigned Transaction of a Signed Transaction carries the inputs, outputs and an optional payload. The Unsigned Transaction is an explicit type of transaction and therefore starts with its own Transaction Type byte which is of value 0.

An Unsigned Transaction must contain at least one input and output.

Inputs

The Inputs part holds the inputs to consume, respectively to fund the outputs of the Unsigned Transaction. There is only one type of input as of now, the UTXO Input.

UTXO Input
Format
Name Type Description
Input Type byte/varint Set to value 0 to denote a UTXO Input.
Transaction ID ByteArray[64] The transaction reference from which the UTXO comes from.
Transaction Output Index byte/varint The index of the output on the referenced transaction to consume.
Unlock Index byte/varint The index of the unlock block unlocking the funds used in this input. Multiple inputs can reference the same unlock block, for example, inputs consuming multiple UTXOs residing on a specific Ed25519 address may reference the same signature unlock block with the corresponding signature unlocking the funds.
Unlock Mode byte/varint Defines the unlock block's type which unlocks this input.
Name Value Description
SIGNATURE 0 A signature unlock block unlocks this input.

An UTXO Input is an input which directly references an output of a previous transaction by using the given transaction's BLAKE2b-256 (TODO: are we going to use this?) hash + the index of the output on that transaction. It defines which unlock block in the unlock blocks part of the Signed Transaction unlocks this input with the type the unlock block must have.

Example: If the output the input references outputs to an Ed25519 address, then the corresponding unlock block must be of type Signature Unlock Block.

Multiple inputs may reference the same unlock block, for example, if an Unsigned Transaction consumes UTXOs which output to the same Ed25519 address, then one unlock block with the corresponding signature can be used to unlock those inputs.

Outputs

The Outputs part holds the outputs to create with this Unsigned Transaction. There is only one type of output as of now, the SigLockedSingleDeposit.

SigLockedSingleDeposit
Format
Name Type Description
Output Type byte/varint Set to value 0 to denote a SigLockedSingleDeposit.
Address (oneOf)
Ed25519 Address
Name Type Description
Address Type byte/varint Set to value 0 to denote an Ed25519 Address.
Address ByteArray[32] The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
WOTS Address
Name Type Description
Address Type byte/varint Set to value 1 to denote a WOTS Address.
Address ByteArray[49] The T5B1 encoded WOTS address.
Amount uint64 The amount of tokens to deposit with this SigLockedSingleDeposit output.

The SigLockedSingleDeposit defines an output (with a certain amount) to a single target address which is unlocked via a signature proving ownership over the given address. Such output can hold addresses of different types.

Payload

The payload part of an Unsigned Transaction can hold an optional payload. This payload must not affect the validity of the Unsigned Transaction. Only the Indexation Payload (TODO: LINK TO RFC) is supported as of now. An Unsigned Transaction holding a payload of a non-supported type is invalid.

Unlock Blocks

The Unlock Blocks part holds the unlock blocks unlocking inputs within an Unsigned Transaction. As of now, only unlock blocks of type Signature Unlock Block exist.

Inputs must specify what type their corresponding Unlock Block is:

Name Value Description
SIGNATURE 0 A signature unlock block.
Signature Unlock Block

A Signature Unlock Block defines an Unlock Block which holds a signature of some type unlocking one or more inputs. Such block signs the entire Unsigned Transaction part of an Signed Transaction including the optional payload.

A Signature Unlock Block first defines its type (this is a type "within" the Signature Unlock Block. It is not the type of the Unlock Block) and then the corresponding data needed to parse and validate the signature. There are two types of Signature Unlock Blocks, one for Ed25519 addresses and one for WOTS addresses.

Ed25519 Signature Unlock Block
Name Type Description
Signature Type byte/varint Set to value 0 to denote an Ed25519 Signature Unlock Block.
Public key ByteArray[32] The public key of the Ed25519 keypair which is used to verify the signature.
Signature ByteArray[64] The signature signing the serialized Unsigned Transaction.
WOTS Signature Unlock Block
Name Type Description
Signature Type byte/varint Set to value 1 to denote a WOTS Signature Unlock Block.
Signature ByteArray The signature signing the serialized Unsigned Transaction.

Validation

A Signed Transaction payload has different validation stages, since some validation steps can only be executed if certain information becomes present, respectively should have become present. We therefore distinguish between syntactical- and semantic validation.

Syntactical Validation

This validation can commence as soon as the transaction data has been received in its entirety. It validates the structure but not the signatures of the transaction. If the transaction does not pass this stage, it must not be further broadcasted and can be discarded.

Following criteria defines whether the transaction passes the syntactical validation:

  • Transaction Type value must be 0, denoting an Unsigned Transaction.
  • Inputs:
    • Inputs Count must be 0 < x ≤ 127.
    • At least one input must be present in the transaction.
    • Input Type value must be 0, denoting an UTXO Input.
    • UTXO Input:
      • Transaction Output Index must be 0 ≤ x ≤ 127.
      • Unlock Index must be ≤ highest seen index + 1. The first defined input must start at index 0. Sequence examples of inputs Unlock Indices:
        • Valid sequence: 0, 0, 1, 2, 1, 3.
        • Invalid sequence: 0, 1, 2, 4 or 0, 1, 2, 3, 6, 4
      • Unlock Mode must be 0 (denoting a Signature Unlock Block).
      • Inputs must be in lexicographical order by their specified Transaction ID.
  • Outputs:
    • Outputs Count must be 0 < x ≤ 127.
    • Output Type must be 0, denoting a SigLockedSingleDeposit.
    • SigLockedSingleDeposit:
      • Address Type must either be 0 or 1, denoting an Ed25519- or WOTS address.
      • If Address is of type WOTS address, its bytes must be valid T5B1 bytes.
      • Amount must be > 0.
    • Accumulated output balance must not exceed the total supply of tokens 2'779'530'283'277'761.
  • Payload Length must be 0 (to indicate that there's no payload) or be valid for the specified payload type.
  • Payload Type must be 0 if Payload Length is not 0, denoting an Indexation Payload.
  • Unlock Blocks Count must match the amount of mentioned unique Unlock Indices specified in the inputs. Must be 0 < x ≤ 127.
  • Signature Unlock Block Type must either be 0 or 1, denoting an Ed25519- or WOTS Signature Unlock block.
  • Given the type and length information, the Signed Transaction must consume the entire byte array the Payload Length field in the Message defines.

Semantic Validation

Semantic validation starts when a message which is part of a confirmation cone of a milestone, is processed in the White-Flag ordering. Semantics are only validated during White-Flag confirmations to enforce an ordering which can be understood by all the nodes (i.e. milestone cones), no matter in which order transactions are received. Otherwise, if semantic validation would occur as soon as a transaction would be received, it could potentially lead to nodes having different views of the UTXOs available to spend.

Processing transactions in the White-Flag ordering enables users to spend UTXOs which are in the same milestone confirmation cone, if their transaction comes after the funding transaction in the mentioned White-Flag ordering. It is recommended that users spending unconfirmed UTXOs attach their message directly onto the message containing the source transaction.

Following criteria defines whether the transaction passes the semantic validation:

  1. The UTXOs the transaction references must be known (booked) and unspent.
  2. The transaction is spending the entirety of the funds of the referenced UTXOs to the ouputs.
  3. The address type of the referenced UTXO must match the type of Signature Unlock Block type.
  4. The Signature Unlock Blocks are valid, i.e. the signatures prove ownership over the addresses of the referenced UTXOs.

If a transaction passes the semantic validation, its referenced UTXOs must be marked as spent and the corresponding new outputs must be booked/specified in the ledger. The booked transaction then also becomes part of the White-Flag Merkle tree inclusion set.

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

Drawbacks

Why should we not do this?

Rationale and alternatives

  • Why is this design the best in the space of possible designs?
  • What other designs have been considered and what is the rationale for not choosing them?
  • What is the impact of not doing this?

Unresolved questions

  • What parts of the design do you expect to resolve through the RFC process before this gets merged?
  • What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
  • What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment