This page outlines the fundamental changes to the IOTA protocol which will be deployed in 2021 in a release called Chrysalis.

What is Chrysalis

The objective of the IOTA Foundation is to optimize the IOTA mainnet before Coordicide and to offer an enterprise-ready solution for our ecosystem. This will be achieved by an intermediate update called Chrysalis. This post explains what the Chrysalis upgrade entails.

A chrysalis is “the form a caterpillar takes before it emerges from its cocoon as a fully-formed moth or butterfly”. In the context of IOTA, Chrysalis is the mainnet’s intermediate stage before Coordicide is complete. The main purpose of Chrysalis is to improve the usability of the current IOTA mainnet, for users and developers alike.

Why is this process of adopting major protocol improvements relatively unique to IOTA among permissionless DLTs? The simple answer is the absence of miners. In most permissionless DLTs, the miners’ economic incentives differ from those of regular network users. Changes to throughput and network latencies can disrupt the fee market the miners rely on. This in turn makes them likely to object to network upgrades as it affects their bottom line.

In IOTA, validators and users are one and the same. There is no conflict of interests between parties with different motivations, meaning there is a much smoother path to network improvements. This is why we are able to incrementally and smoothly upgrade the network before Coordicide.

What are the specific Chrysalis upgrades?

White-flag approach

The White-flag approach which is used for calculating balances. It is a simpler, conflict-ignoring approach that improves the speed and efficiency of tip selection, eliminates many network attacks, and significantly reduces the need for reattachments.

New milestone selection algorithm

A new milestone selection algorithm for the coordinator, that focuses on allowing the network to support much more confirmed transactions per second (CTPS) than before with higher computational efficiency.

URTS tip selection

A new Uniform random tip selection in node software. It is significantly faster and more efficient than the previous tip selection algorithm.

Ed25519 signature scheme

The Ed25519 signature scheme has been added to the network, replacing the current Winternitz one time signature scheme (W-OTS) signature scheme. Using an EdDSA signature scheme allows the protocol and clients using the protocol to run more efficiently on established hardware. Unlike W-OTS, the scheme also allows for the re-use of private keys, and, with that, introduces reusable addresses to the protocol. This change also dramatically reduces the transaction size, saving network bandwidth and processing time.

Atomic transactions

Atomic transactions that move the protocol from the current, complicated, bundle construct and use simpler atomic transactions instead. This results in much simpler development and more adaptable and maintainable code of the core software. In addition, atomic transactions reduce network overhead, reduce transaction validation and signature verification load, and improve spam protection and congestion control.

Switch to UTXO Model

A switch to the UTXO model from the current account model. Every coin on an address becomes uniquely identifiable and every spend names the exact coins that it wants to move. This allows for faster and more exact conflict handling and improves resilience and security of the protocol. In addition, switching to UTXO makes other functionalities, such as colored tokens, on the protocol possible in the future.

Internal Binary Representation

A switch to an internal binary representation of the trinary transaction. This allows us to work on binary data for validation, IO, and other processing without the current reliance on binary-ternary conversions as in the pre-Chrysalis software node software. The switch to binary transactions further reduces the transaction size, saving network bandwidth and processing time.

New node API and client libraries

With Chrysalis, we wanted to offer a more standard API on both the node and client library level. Node implementations provide a completely redesigned RESTful and eventful API implementations.

Our client libraries provide high level abstractions that allow developers to build solutions that are easier to develop and cheaper to maintain.

Path to Chrysalis

One of the IOTA Foundation’s primary roles is defining and delivering on a development roadmap that aligns with the Foundation's strategy to reach production-readiness and adoption.

The IOTA mainnet has been operational since 2016 and the overall engineering strategy evolved significantly based on industry demand and feedback.

Progress in Coordicide research has resulted in identifying many concepts that could already be implemented on the current IOTA mainnet and provides significant value to users of the protocol before Coordicide. This led to the formalization of our engineering strategy around Chrysalis: a series of upgrades to the protocol that achieves production-readiness before Coordicide.

The benefit of this approach is that many of the protocol properties will remain the same, or almost the same, for Coordicide. That, together with a better set of developer tools, will make the transition to Coordicide much simpler.

The intended outcomes for Chrysalis are:

  • Simpler transition to Coordicide - With Coordicide making significant progress, we want to ensure that all developers and companies that build and deploy on Chrysalis will have as smooth a transition to Coordicide as possible.
  • Substantial performance improvements - With the changes introduced by Chrysalis, we will see a substantial improvement in the scalability and reliability of the IOTA Mainnet.
  • Improved developer and user experience - The new protocol features, new libraries, and the new wallet will make IOTA one of the best platforms to build on, removing the friction which developers experience today while allowing solutions built on top of the protocol to provide better user experience.
  • Accelerated adoption - Chrysalis will make IOTA production-ready; becoming a stable protocol, with a reliable set of developer tools and frameworks that will enable startups, corporations, and governments to develop and launch products powered by IOTA.

The stages to Chrysalis

The Chrysalis upgrade is a complex undertaking. We are coordinating a number of distinct products to ensure a smooth transition for IOTA’s current users and partners. In addition to the core node software, we also need to update our wallet software, our libraries, and the entire infrastructure.

Another important requirement is the ease of transition to the future Coordicide network. By carefully planning the breaking changes introduced along the way, and providing support in our developer tools, we will ensure that our growing ecosystem of developers, startups, and corporations can reliably develop and launch new innovative products on IOTA.

The plan for implementing Chrysalis is divided into two phases.

The first phase consisted of improved tip selection (URTS), milestone selection, and White flag. These were implemented in the node software gradually. This phase required an upgrade of all nodes, including the coordinator node, and did not require a snapshot.

The first phase of Chrysalis resulted in:

  • Transaction confirmation times of around 10 seconds
  • Transactions rarely needing reattachment
  • A substantial TPS increase
  • Performance and reliability improvements for nodes

The second phase of Chrysalis consists of adopting and/or implementing UTXO, atomic transactions, reusable addresses (Ed25519), a transition to a binary transaction layout, and a new set of client libraries and developer tools. These represent significant changes to the core protocol and the way transactions are structured. Once everything has been tested, validated, and audited, the Foundation will deploy a new Chrysalis network. The upgrade will consist of an extended period when the current, legacy network remains operational. This allows users, exchanges, and partners to migrate to the Chrysalis network at will. The migration is not time constrained.

The second phase of Chrysalis consists of:

  • Reusable addresses and support for more standard cryptography (EdDSA), making efficient hardware support for all major architectures possible
  • A simplified transaction layout and a reduction in transaction size, further increasing performance and efficiency
  • Significant improvements to the usability and reliability of IOTA
  • A switch to a UTXO based model from the current account model

The introduction of reusable addresses is an important change for token holders. This will vastly improve IOTA’s usability and make integration into new exchanges, wallets, and payment systems much simpler. A new wallet, called Firefly, will be released with Chrysalis. This wallet will allow token holders to transition from the current WOTS address scheme to the new EdDSA scheme.

Our goal is to make this transition as seamless as possible for everyone in the IOTA ecosystem. This includes a variety of improvements and updates to our libraries and software, as well as training and educational sessions for our partners.

From plan to action

With Chrysalis, we had to make decisions on how to best implement all the upcoming changes, ensuring a correct and timely implementation. What follows is an overview of the various components we are working on to successfully implement this update.

Specification and standardization

Specifications are a major part of our new development process. All our new software projects (Node software, Wallet, Identity, Access, Streams, etc.) are based on vetted specifications. Specifications make it possible for external parties to follow a project’s intended functionality, for example for audit purposes, or develop their own implementations in different languages.

The Chrysalis changes are specified in the form of RFCs. You can find all the RFCs in the protocol-rfcs repository. The list of Chrysalis RFCs includes:

Wallet support

The Trinity wallet is a popular IOTA wallet. With Chrysalis, we will release a new wallet implementation, Firefly. The team has been working on a complete reevaluation of the wallet architecture, with a completely redesigned user experience. At its core will be a new wallet library written in Rust. The wallet library is designed to allow other developers to easily implement IOTA wallets within their applications. Another new Rust library utilized by Firefly is Stronghold; Stronghold enables ultra-secure secret handling and storage.


Currently, the IOTA Foundation supports two public Networks: Mainnet and Devnet (Devnet is for PoCs and application tests). Both networks provide public endpoints for users and partners. You can read more about the networks and how you can participate in our documentation.

While the current Mainnet will be replaced by a new network, it will remain operational for an extended period of time. For the purposes of non-time-constrained transition of projects deployed on Devnet, the Devnet will only be upgraded after the Chrysalis release.

The Chrysalis testnet has been operational since December and we encourage everyone to use it to build and test their solutions before the official launch of Chrysalis.

Chrysalis Testnet

Nodes deployed to the testnet can be queried using a load balancer at:

  • api.lb-0.testnet.chrysalis2.com

We recommend using the load balancer for most scenarios.

Single node endpoints that expose native MQTT in case you need this are:

  • api.hornet-0.testnet.chrysalis2.com
  • api.hornet-1.testnet.chrysalis2.com
  • api.hornet-2.testnet.chrysalis2.com
  • api.hornet-3.testnet.chrysalis2.com


Chrysalis is the most promising series of upgrades made to IOTA yet. It is a major step for our production-readiness, with increased transaction throughput, network stability, improved usability, and enables new features and use cases. The upcoming weeks and months are some of the most exciting in IOTA’s history. We are on a clear path towards IOTA’s adoption as an enabling technology for IoT and beyond.


Firefly is IOTA's new official wallet for Chrysalis.

GitHub: https://github.com/iotaledger/firefly

Verify your Firefly desktop download

When you download Firefly Desktop, you may want to verify its authenticity to make sure that you downloaded the correct one from the IOTA Foundation GitHub repository. In this tutorial, you learn how to verify Firefly Desktop downloads.

To verify the authenticity of Firefly Desktop, you can check its SHA256 hash and its code signature. Instructions for both of these steps differ, depending on your operating system.

Windows operating system

Verify the SHA256 hash

  1. Open a command-line interface

  2. Create a SHA256 hash of the Firefly Desktop .exe file. Replace the path with the path to your Firefly .exe file.

certUtil -hashfile path\to\firefly-desktop-version.exe SHA256

For example, if the file is in the C:\Users\yourname\Downloads directory, do the following:

certUtil -hashfile C:\Users\yourname\Downloads\firefly-desktop-1.0.0.exe SHA256
  1. Compare your SHA256 hash with the one in the release notes and make sure that they match

Verify the code signature

  1. Right-click on firefly-desktop-version.exe

  2. Go to Digital Signatures > Details > View Certificate

  3. In the Certification Path tab, make sure that the path matches the following information:

    • DigiCert
    • DigiCert SHA2 Assured Code Signing CA
    • IOTA Stiftung
  4. Make sure that the Certificate status reads "This certificate is OK."

MacOS operating system

Verify the SHA256 hash

  1. Open Terminal (in /Applications/Utilities/Terminal)

  2. Create a SHA256 hash of the Firefly Desktop .dmg file. Replace the path with the path to your Firefly .dmg file.

shasum -a 256 /path/to/firefly-desktop-version.dmg

For example, if the file is in ~/Downloads, do the following:

shasum -a 256 ~/Downloads/firefly-desktop-1.0.0.dmg
  1. Compare your SHA256 hash with the one in the release notes and make sure that they match

Verify the code signature


To follow these instructions you need the Xcode Command Line Tools.

  1. Open Terminal (in /Applications/Utilities/Terminal)

  2. Verify the Firefly.app file's signature. Replace the path with the path to your Firefly.app file. This command confirms whether the code binaries are actually signed, the signature is valid, all the sealed components are unaltered, and the signature passes some basic consistency checks.

    codesign -d -vv /path/to/Firefly.app

    For example, if the file is in the /Applications directory, do the following:

    codesign -d -vv /Applications/Firefly.app
  3. Make sure that the following information matches the output of the command:

    Authority=Developer ID Application: IOTA Stiftung (UG77RJKZHH)
    Authority=Developer ID Certification Authority
    Authority=Apple Root CA
  4. Test the signature against system policies. Replace the path with the path to your Firefly.app file.

    spctl -a -vv path/to/Firefly.app

    For example, if the file is in the /Applications directory, do the following:

    spctl -a -vv /Applications/Firefly.app
  5. Make sure that the following information matches the output of the command (assuming Firefly is in the /Applications directory):

    /Applications/Firefly.app: accepted
    source=Developer ID
    origin=Developer ID Application: IOTA Stiftung (UG77RJKZHH)

Linux operating system

Verify the SHA256 hash


To follow these instructions you need the sha256sum package, which is included with most Linux distributions.

  1. Open Terminal

  2. Create a SHA256 hash of the Firefly Desktop executable file. Replace the path with the path to your Firefly executable file.

sha256sum path/to/firefly-desktop-version.AppImage

For example, if the file is in ~/Downloads, do the following:

sha256sum ~/Downloads/firefly-desktop-1.0.0.AppImage
  1. Compare your SHA256 hash with the one in the release notes and make sure that they match

Verify the code signature

  1. Download the .asc and .gpg files in the Assets section of the release notes

  2. Import the Firefly GPG key from keyserver.ubuntu.com

    gpg --keyserver keyserver.ubuntu.com --recv 466385BD0B40D9550F93C04746A440CCE5664A64
  3. Make sure that the following information matches the output of the command:

    gpg: key 46A440CCE5664A64: public key "IOTA Foundation (IOTA Foundation Identity) <contact@iota.org>"
  4. Verify the signature

    gpg --verify path/to/firefly-desktop-version.AppImage.asc path/to/firefly-desktop-version.AppImage

    For example, if the .asc and .AppImage files are both in ~/Downloads, do the following:

    gpg --verify ~/Downloads/firefly-desktop-1.0.0.AppImage.asc ~/Downloads/firefly-desktop-1.0.0.AppImage
  5. Make sure that the following information matches the output of the command:

    gpg: Good signature from "IOTA Foundation (IOTA Foundation Identity) <contact@iota.org>"

Node software

We have been running the network exclusively on the Go powered Hornet node since the summer of 2020. For Chrysalis, you will have the choice to continue using a new version of Hornet or our new Rust-based Bee node.

Hornet and Bee

Moving forward, both Hornet and Bee are the officially supported nodes for IOTA.

Hornet is an EDF-supported community node written in Go and has already proven itself to be a stable and performant implementation. It recently underwent a successful audit.

Bee is an IOTA Node implemented by the Foundation and written in Rust.

At this stage, we recommend using Hornet since it has several optional features that are not implemented in Bee so far.

Node software

Node API specification


The IOTA client libraries allow you to easily integrate IOTA into your own applications. You can choose a library to match your use case.

Official IOTA libraries serve as one-source-code-of-truth to IOTA users and provide binding to other programming languages. You can read more about core principles behind IOTA client libraries in the following blog post.

  • client-lib: a general purpose IOTA client library for interacting with the IOTA network (Tangle)
  • wallet-lib: a stateful library specifically designed to be used for IOTA value-based transfers
  • iota.c: a special-purpose library in C for embedded devices (with microcontrollers) covering a basic features of client-lib or wallet-lib
  • iota.js: an initial IOTA client library in Typescript that can be used in a web browser
  • iota.go: an initial IOTA client library in Golang


All libraries are in active development. The libraries target the Chrysalis testnet and do not work with current IOTA mainnet.

The client libraries with official support are maintained by the IOTA Foundation, their source code can be found on the Official GitHub repository.


Developer tools

IOTA Client Library

The official client library for interacting with the IOTA Tangle allows you to:

  • Create messages and transactions
  • Sign transactions
  • Generate addresses
  • Interact with an IOTA node

If you mainly intend to process value transfers, we recommend you use our stateful wallet library instead.

IOTA Client Library full documentation


  • Getting Started - Getting Started with Rust and the IOTA Client Library.
  • Examples - Find starting points or inspiration in the examples.
  • Repository - Browse through the code and learn what's happening behind the scenes. Pull requests are very welcome!
  • API Documentation - The IOTA Client Library Rust API Documentation.


  • Getting Started - Getting Started with Node.js and the IOTA Client Library.
  • Examples - Find starting points or inspiration in the examples.
  • Repository - Browse through the code and learn what's happening behind the scenes. Pull requests are very welcome!
  • API Documentation - The IOTA Client Library Node.js API Documentation.


  • Getting Started - Getting Started with Python and the IOTA Client Library.
  • Examples - Find starting points or inspiration in the examples.
  • Repository - Browse through the code and learn what's happening behind the scenes. Pull requests are very welcome!
  • API Documentation - The IOTA Client Library Python API Documentation.


  • Getting Started - Getting Started with C and the IOTA Client Library.
  • Examples - Find starting points or inspiration in the examples.
  • Repository - Browse through the code and learn what's happening behind the scenes. Pull requests are very welcome!
  • API Documentation - The IOTA Client Library C API Documentation.

IOTA Wallet Library

The wallet library is a stateful library for developers; essentially it's a programmable wallet. It is recommended you use this library if you are mainly using IOTA for token transfers. This library supports the handling and monitoring multiple account/addresses at the same time. Its stateful design allows a management of multiple accounts and addresses in an effective manner.

In addition to this, it also supports the Stronghold.rs enclave, incorporating the best security practices in one package:

IOTA Wallet Library full documentation


  • Getting Started - Getting Started with Rust and the IOTA Wallet Library.
  • Examples - Find starting points or inspiration in the examples.
  • Repository - Browse through the code and learn what's happening behind the scenes. Pull requests are very welcome!
  • API Documentation - The IOTA Wallet Library Rust API Documentation.


  • Getting Started - Getting Started with Node.js and the IOTA Wallet Library.
  • Examples - Find starting points or inspiration in the examples.
  • Repository - Browse through the code and learn what's happening behind the scenes. Pull requests are very welcome!
  • API Documentation - The IOTA Wallet Library Node.js API Documentation.


  • Getting Started - Getting Started with Python and the IOTA Wallet Library.
  • Examples - Find starting points or inspiration in the examples.
  • Repository - Browse through the code and learn what's happening behind the scenes. Pull requests are very welcome!
  • API Documentation - The IOTA Wallet Library Python API Documentation.

IOTA Chrysalis Guides

Overall changes from IOTA 1.0 to 1.5 (Chrysalis) in a nutshell

  • The format of the address was changed and it is based on both derivation path and bech32 standards. See IOTA address anatomy
  • The concepts of bundles and transactions were replaced with the concepts of messages and payloads. The message is a data structure that is actually being broadcast in the network and represents a node (vertex) in the Tangle graph. See messages, payload and transactions and selected message payloads
  • The IOTA network is based on a DAG (Directed Acyclic Graph) to store individual messages (and related transactions). However, each message can newly reference up to 8 parent messages. See messages, payload and transactions
  • The signature scheme based on WOTS was replaced with with Ed25519 signature scheme. See seed and addresses
  • Due to the changed signature scheme, IOTA addresses are reusable without any negative security impact
  • In comparison to IOTA 1.0, which was based on ternary, IOTA 1.5 is based on binary and is thus very efficient on all kinds of current hardware devices
  • In contrast to IOTA 1.0, IOTA 1.5 addresses are perfectly reusable; even if one spends funds from the given address, it can be used again. See address/key space
  • Originally, IOTA 1.0 used an account-based model for tracking individual iota tokens. Chrysalis embraced Unspent Transaction Output (also known as UTXO) model to track tokens and token holders. See Unspent Transaction Output
  • The approach to client libraries was completely reengineered from the ground up. There are new official client libraries that serve as one-source-code-of-truth to IOTA users and can be combined in a modular fashion based on particular use cases. All libraries provide a binding to other programming languages. See client libraries
  • Our official iota tools, such as wallet software, use the same libraries under the hood and so any developer may taste the same dog food as we do
  • The official client libraries embraced Hierarchical Deterministic Wallets approach which is fully BIP44 compatible. See address/key space
  • There is a new official wallet software called Firefly. See firefly beta release

Developer guide to Chrysalis

This is a quick guide meant to help you navigate through some of the differences you will encounter while migrating from IOTA 1.0 to IOTA 1.5, also known as Chrysalis.

Seed and addresses

In Chrysalis, all ternary conversions apart from PoW have been removed which results in a better, faster developer experience. Additionally, the WOTS-Signature has been replaced by a Ed25519 signature scheme. This means that you can now use an address multiple times to send and receive coins.

With these changes, and the further adoption of industry standards, both seeds and addresses will look completely different in IOTA Chrysalis.

IOTA 1.0 address:


IOTA 1.5 (Chrysalis) address (bech32 standard):

Mainnet with iota


Testnet with atoi


IOTA 1.5 address anatomy

The IOTA address is based on the Ed25519 signature scheme and it is usually represented by the Bech32 (checksummed base32) format string of 64 characters or hex format:

three distinguished parts
human-readable id
iota | atoi
48 bytes [0..9a..z]
6 characters [0..9a..z]
iota = mainnet; atoi = testnet

More information: Protocol-rfc#0020


With the new wallet library, developers do not need to use a self-generated seed anymore. By default, the seed is created and stored in Stronghold, our in-house built security enclave. It is not possible to extract the seed from Stronghold for security purposes. Stronghold uses encrypted snapshots that can easily be backed up and securely shared between devices. These snapshots are then further secured with a password.

More information about IOTA Wallet Library is available on Wallet docs page or in the Exchange guide, which is mainly focused on value transactions.

Please note, it is highly recommended to NOT use online seed generators at all. The seed is the only key to the given funds.

A root of the Ed25519 signature scheme is basically a 32-byte (256-bit) uniformly randomly generated seed based on which all private keys and corresponding addresses are generated. A seed may be represented by a string of 64 characters using [0-9a-f] alphabet (32 bytes encoded in hexadecimal).

The seed can be, for example, generated using the SHA256 algorithm on some random input generated by cryptographically secure pseudo-random generator, such as os.urandom().

Seed examples (a single seed per line):


In modern wallet implementations, such as our wallet.rs library and firefly wallet, the seed is usually generated from a seed mnemonic (seed phrase), using BIP39 standard, to be better memorized/stored by humans. It is based on randomly generated list of english words and is later used to generate the seed. Either way, the seed is a root for all generated private keys and addresses


Address/key space

As mentioned above, IOTA 1.5 embraced some existing industry standards, which is obvious even during an address generation process. This includes the BIP32 standard that describes an approach to Hierarchical Deterministic Wallets. The standard was improved by BIP44 recently.

These standards define a tree structure as a base for address and key space generation which is represented by a derivation path:

m / purpose / coin_type / account / change / address_index
  • m: a master node (seed)
  • purpose: constant which is {44}
  • coin_type: a constant set for each crypto currency. IOTA = 4218, for instance.
  • account: account index. Zero-based increasing int. This level splits the address/key space into independent branches (ex. user identities) which each has own set of addresses/keys
  • change: change index which is {0, 1}, also known as wallet chain.
    There are two independent chain of addresses/keys. 0 is reserved for public addresses (for coin receival) and 1 is reserved for internal (also known as change) addresses to which a transaction change is returned. In comparison to IOTA 1.0, IOTA 1.5 is fine with address reuse, and so it is, technically speaking, valid to return transaction change to the same originating address. It is up to developers whether to leverage it or not. iota.rs library and its sibling wallet.rs help with either scenario.
  • address_index: address index. Zero-based increasing int that indicates an address index

As outlined, there is a large address/key space that is secured by a single seed.

And there are few additional things to note:

  • Each level defines a completely different subtree (subspace) of addresses/keys and those are never mixed up
  • The hierarchy is ready to "absorb" addresses/keys for different coins at the same time (coin_type) and all those coins are secured by the same seed
  • There may be also other purposes in the future. However, let's consider a single purpose as of now. The constant 44 stands for BIP44.
  • The standard was agreed upon different crypto communities, although not all derivation path components are always in active use. For example, account is not always actively leveraged across crypto space (if this is a case then there is usually account=0 used)
  • Using different accounts may be useful to split addresses/key into some independent spaces and it is up to developers to implement.

Please note, having many different accounts may have a negative impact on performance while account discovery phase. So, if you are after using multiple, different accounts then you may be interested in our stateful library wallet.rs that incorporates all business logic needed to efficiently manage independent accounts. Additionally, our exchange guide provides some useful tips how different accounts may be leveraged.


So in case of IOTA 1.5 (Chrysalis), the derivation path of address/key space is [seed]/44/4218/{int}/{0,1}/{int}:

  • The levels purpose and coin_type are given
  • The rest levels are up to developers to integrate, specifically seed, account, wallet_chain and address_index


Messages, payloads, and transactions

In comparison to original the IOTA 1.0, IOTA 1.5 also introduced some fundamental changes to the underlying data structures. The original concept of transactions and bundles is gone, and has been replaced by a concept of messages and payloads.

A message is a data structure that is actually being broadcast in the IOTA 1.5 network and represents a node (vertex) in the Tangle graph.

It can refer to up to 8 previous messages and once a message is attached to the Tangle and approved by a milestone, the Tangle structure ensures the content of the message is unaltered. Every message is referenced by a message_id which is based on a hash algorithm (Blake2b256) of binary content of the message. It also includes previous Tangle messages as its parents which means it is not possible to alter the given message without altering previous messages in the Tangle.

The message is an atomic unit that is confirmed by the network as a whole.

IOTA is no longer based on ternary. IOTA 1.5 uses binary to encode and broadcast all underlying data entities

A message is arbitrary in size (up to 35 kB) and it can hold variable sets of information called payloads. The number of payloads a single message can encapsulate is not given. Even a message without a payload is completely valid and can be broadcast. The Message itself does not include any timestamp; a message timestamp is derived from an acceptance of the given message by the Tangle network.

Apayload represents a layer of concern. Some payloads may change a state of the ledger (ex. SignedTransactions) and some may provide extra features to some specific applications and business use cases (ex. IndexationPayload).

There are already implemented core payloads, such as SignedTransaction, MilestonePayload, and IndexationPayload but the message and payload definition is generic enough to incorporate any future payload(s) the community agrees upon.

Needless to say, the IOTA network ensures the outer structure of the message itself is valid and strictly complies with network consensus protocol. However, the inner structure is very flexible, future-proof, and offers an unmatched network extensibility.


The current IOTA 1.5 network incorporates the following core payloads:

  • SignedTransaction: a payload that describes UTXO transactions that are the cornerstones of value-based transfers in IOTA network. Via this payload, a message can be also cryptographically signed
  • MilestonePayload: a payload that is emitted by the Coordinator
  • IndexationPayload: a payload that enables the addition of an index to the encapsulating message, as well as some arbitrary data. The given index can be later used to search the message(s).

In comparison to IOTA 1.0, a message itself is not directly related to the IOTA address while broadcasting to the IOTA 1.5 network. Such messages are referenced using message_id. Messages are indirectly related to IOTA addresses via SignedTransaction payload, specifically the UTXO section.

Protocol-rfc#0017; Protocol-rfc#0018

Unspent Transaction Output (UTXO)

Originally, IOTA 1.0 used an account-based model for tracking individual iota tokens: each IOTA address held a number of tokens and the aggregated number of tokens from all iota addresses was equal to the total supply.

In contrast, IOTA 1.5 uses the unspent transaction output model, or UTXO. It is based on an idea to track unspent amounts of tokens via a data structure called output.

Below is a simplified analogy of how the UTXO works:

  • There are 100 tokens recorded in the ledger as Output A and this output belongs to Alice. So, the initial state of the ledger: Output A = 100 tokens
  • Alice sends 20 tokens to Paul, 30 tokens to Linda, and keeps 50 tokens at her disposal
  • Her 100 tokens are recorded as Output A so she has to divide (spent) tokens and create three new outputs:
    Output B with 20 tokens that goes to Paul, Output C with 30 tokens that goes to Linda, and finally Output D with the rest of the 50 tokens that she kept for herself
  • Original Output A was completely spent and cannot be used any more. It has been spent and so becomes irrelevant to ledger state.
  • New state of ledger: Output B = 20 tokens, Output C = 30 tokens and Output D = 50 tokens
  • The total supply remains the same, just number of outputs differs and some outputs were replaced by other outputs in the process


The key takeaway of the outlined process above is the fact that each unique output can be spent only once. Once the given output is spent, it cannot be used any more and is irrelevant in regards to the ledger state.

So even if Alice still wants to keep remaining tokens at her fingertips, those tokens have to be moved to a completely new output that can be, for instance, still tied to the Alice's same iota address as before.

Every output also stores information about an IOTA address to which it is coupled with. So addresses and tokens are indirectly coupled via outputs. Basically, the sum of outputs and their amounts under the given address is a balance of the given address, ie., the number of tokens the given address can spend. And the sum of all unspent outputs and their amounts is equal to the total supply.

Outputs are being broadcasted encapsulated in a message as a part of SignedTransaction payload.


Selected message payloads

Currently, there are two commonly used message payloads, IndexationPayload and SignedTransaction which can be combined based as needed.



IndexationPayload is a payload type that can be used to attach an arbitrary data and key index to a message. When this particular payload is leveraged, then a message and related data entity can be searched via key index in addition to a message_id.


SignedTransaction is a payload type that is used to transfer value-based messages as UTXO. It changes the ledger state as old outputs are being spent (replaced) and new outputs are being created.

Each SignedTransaction includes the following set of information:

  • inputs - a list of valid outputs that should be used to fund the given transaction. Outputs are uniquely referenced via previous transaction_id and inner index. At least one output has to be given with enough balance to source all outputs of the given message
  • outputs - a list of IOTA address(es) and related amount(s) the input outputs should be split among. Based on this information, new UTXO outputs are being created
  • unlock_blocks - it includes a transaction signature(s) (currently based on Ed25519 scheme) that proves token ownership based on a valid seed

Dust protection

Since IOTA is feeless and has the ability to send microtransactions, attackers could use this to spam the network with very low value transactions, which we call dust. To avoid this, we only allow microtransaction below 1Mi (dust) of IOTA tokens to another address if you already have at least 1Mi as a dust allowance output on that address. The number of allowed dust outputs on an address is the amount of the dust allowance outputs divided by 100,000 and rounded down, i.e. 10 outputs for each 1 Mi deposited, with a maximum of 100 dust outputs in total.

In the UTXO model, each node in the network needs to keep track of all the currently unspent outputs. When the number of outputs becomes too large, it can cause performance and memory issues. The RFC below proposes a new protocol rule regarding the processing of outputs where they transfer a very small amount of IOTA’s so-called dust outputs. Dust outputs are only allowed when they are backed up by a certain deposit on the receiving address. This limits the amount of dust outputs, thus making it expensive to proliferate dust. Since a receiver must make a deposit, the protocol makes receiving dust an opt-in feature.


Up to 8 Parents

With IOTA 1.0, you always had to reference 2 parent transactions. With Chrysalis, we introduce a more dynamic number of parent nodes where you can reference up to 8 parents. We recommend you reference at least 2 unique parents at all times for the best possible results.


Exchange guide

The IOTA wallet library

Easily integrate IOTA with your exchange, custody solution, or product.

IOTA is built on an architecture that was designed to be the backbone of the Internet of Things (IoT) environment of the future. But this architecture has made it more challenging for service providers like exchanges to integrate IOTA compared to traditional blockchain-based distributed ledgers.

Within the Chrysalis update (also known as IOTA 1.5), some building blocks have been changed to be more approachable and more aligned with currently leveraged standards. We also ship many client libraries to help developers implement IOTA into their applications: layers

How do I implement it to my exchange?

In wallet.rs, we use an account model so you can create an account for each of your users. Another approach would be to use one account and generate multiple addresses, which you can then link to the users in your database. The wallet library is designed to be as flexible as possible to back up any of your use cases.

Since IOTA addresses in the Chrysalis network are perfectly reusable, they can be mapped to your users in a clear and concise way:

  • Create an account for every user -> Multi Account approach
  • Create one account with many addresses -> Single account approach

The library supports derivation for multiple accounts from a single seed. An account is simply a deterministic identifier from which multiple addresses can be further derived.

The library also allows consumers to assign a meaningful alias to each account. In addition to this, generated individual accounts can be also searched via generated addresses. This means it does not matter whether aliases or addresses are known as the search for the related account is very straightforward using the wallet.rs library.

It also leaves the choice to users if they want to segregate their funds across multiple accounts or multiple addresses. The following illustration outlines the relationships between seed, accounts, and addresses:


Multi account approach

The multi account approach is used to create an account for each individual user. The created accounts can then be linked to the internal user IDs as an account alias, which are distinctly separated.

Single account approach

The single account approach allows for just one account and creates addresses for each individual user. The associated addresses are then linked to the internal user IDs and store who owns which address in the database. Most exchanges are more familiar with the single account approach and find it easier to use, implement, and backup.

Implementation guide

This guide explains how to use the IOTA Wallet Library to successfully implement IOTA into an exchange. If you already implemented the IOTA Hub, please visit the Hub Migration Guide.

Features of the Wallet Library:

  • Secure seed management
  • Account management (with multiple accounts and multiple addresses)
  • Confirmation monitoring
  • Deposit address monitoring
  • Backup and restore functionality

How does it work?

The Wallet Library is a stateful package with a standardized interface for developers to build applications involving IOTA value transactions. It offers abstractions to handle IOTA payments and can optionally interact with the IOTA Stronghold for seed handling, seed storage, and state backup. Alternatively, you can use a SQLite database; however, using the Stronghold component is highly recommended due to the most advanced level of security being applied.

For reference, you can see the full documentation here.

The following examples cover the multi account approach using NodeJS binding:

  1. Setup the Wallet Library
  2. Create an account for each user
  3. Generate a user address for deposits
  4. Listen to events
  5. Check the user balance
  6. Enable withdrawals

Note: If you are looking for other languages, please read the wallet library overview.

Since all wallet.rs bindings are based on core principles provided by the wallet.rs library, the outlined approach is very similar regardless of the programming language of your choice.

1. Setup the Wallet library

First, let's install the components that are needed to use wallet.rs and the binding of your choice; it may vary a bit from language to language. In the case of the NodeJs binding, it is quite straightforward since it is distributed via the npm package manager. We also recommend you use dotenv for password management.

For reference, read more about backup and security here.

npm install @iota/wallet dotenv
touch .env

Then, input your password to the .env file like this:

SH_PASSWORD="here is your super secure password"

Once you have everything needed to use the wallet.rs library, it is necessary to initialize the AccountManager instance which creates (opens) a secure storage for individual accounts (backed up by Stronghold by default).

The storage is encrypted at rest, so you need a strong password and location where to put your storage.

Note: manage your password with the utmost care.

Technically speaking, "storage" means a single file called wallet.stronghold. It is also needed to generate a seed (mnemonic) that serves as a cryptographic key from which all accounts and related addresses are generated.

One of the key principles behind the stronghold-based storage is that no one can get a seed from the storage. You deal with all the accounts purely via the Account_Manager instance where all complexities are hidden under the hood and are dealt with in a secure way. In case you would also like to store a seed somewhere else, there is another method, AccountManager.generateMnemonic(), that generates random seeds. This method can be leveraged before the actual account initialization.

Note that it is highly recommended to store the stronghold password and the stronghold database on separate devices. Please refer to the backup and security guide for more information.

Import the Wallet Library and create an account manager:

    const { AccountManager, SignerType } = require('@iota/wallet')

    // Setup IOTA Wallet Library
    const manager = new AccountManager({
        storagePath: './storage'
    manager.storeMnemonic(SignerType.Stronghold, manager.generateMnemonic()) // seed generation

Once the stronghold storage is created, it is not needed to generate the seed any longer (manager.storeMnemonic(SignerType.Stronghold, manager.generateMnemonic())). It has been already saved in the storage together with all account information.

2. Create an account for an user

Once the backend storage is created, individual accounts for individual users can be created:

    let account = await manager.createAccount({
        alias: user_id,  // an unique id from your existing user
        clientOptions: { node: 'http://api.lb-0.testnet.chrysalis2.com', localPow: false }

Each account is related to a specific IOTA network (mainnet/devnet) which is referenced by a node property, such as node url (in this example, the Chrysalis testnet balancer).

For more information about clientOptions, please refer to Wallet NodeJs API Reference.

The Alias can be whatever fits to the given use case and should be unique. The alias is usually used to identify the given account later on. Each account is also represented by an index which is incremented (by 1) every time a new account is created. Any account can be then referred to via index, alias, or one of its generated addresses.

Once an account has been created, you get an instance of it using the following methods: AccountManager.getAccount(accountId), AccountManager.getAccountByAlias(alias) or AccountManager.getAccounts().

The most common methods of account instance include:

  • account.alias() - returns an alias of the given account
  • account.listAddresses() - returns list of addresses related to the account
  • account.getUnusedAddress() - returns a first unused address
  • account.generateAddress() - generate a new address for the address index incremented by 1
  • account.balance() - returns the balance for the given account
  • account.sync() - sync the account information with the tangle

3. Generate a user address to deposit funds

Wallet.rs is a stateful library which means it caches all relevant information in storage to provide performance benefits while dealing with, potentially, many accounts/addresses.

Note: sync the account info with the network during the wallet manipulation to be sure the storage reflects an actual state of the ledger (network).

Every account can own multiple addresses. Addresses are represented by an index which is incremented (by 1) every time a new address is created. The latest address is accessible via account.latestAddress():

    // Always sync before account interactions
    const synced = await account.sync()

    // By design, the last address of each account is an unused address which can be used as deposit address
    const latestAddress = account.latestAddress()

    console.log('Need a refill? Send it to this address:', latestAddress)

Feel free to fill the address with Testnet Tokens with the IOTA Faucet to test it.

Addresses are of two types, internal and public (external):

  • Each set of addresses are independent from each other and has an independent index id
  • Addresses that are created by account.generateAddress() are indicated as internal=false (public)
  • Internal addresses (internal=true) are called change addresses and are used to send the excess funds to them
  • The approach is also known as a BIP32 Hierarchical Deterministic wallet (HD Wallet)

Note: You may remember IOTA 1.0 network in which addresses were not reusable. It is no longer true and addresses can be reused multiple times in IOTA 1.5 (Chrysalis) network.

4. Listen to events

The Wallet.rs library supports several events for listening. As soon as the given event occurs, a provided callback is triggered.

Below is an example of fetching existing accounts and listening to transaction events coming into the account:

    const { addEventListener } = require('@iota/wallet')

    const callback = function(err, data) {
        if(err) console.log("err:", err)
        console.log("data:", data)

    //Adds a new event listener with a callback in the form of (err, data) => {}. Supported event names:
    addEventListener("BalanceChange", callback)

    // Possible Event Types:
    // ErrorThrown
    // BalanceChange
    // NewTransaction
    // ConfirmationStateChange
    // Reattachment
    // Broadcast

Example output:

data: {
  accountId: 'wallet-account://1666fc60fc95534090728a345cc5a861301428f68a237bea2b5ba0c844988566',
  address: {
    address: 'atoi1q9c6r2ek5w2yz54en78m8dxwl4qmwd7gmh9u0krm45p8txxyhtfry6apvwj',
    balance: 20000000,
    keyIndex: 0,
    internal: false,
    outputs: [ [Object], [Object] ]
  balance: 20000000

accountId can then be used to identify the given account via AccountManager.getAccount(accountId).

For reference, you can read more about events in the API reference.

5. Check the account balance

Get the available account balance across all addresses of the given account:

    // Always sync before account interactions
    const synced = await account.sync()
    let balance = account.balance().available
    console.log('available balance', balance)

6. Enable withdrawals

Sending tokens is performed via the SyncedAccount instance that is a result of the account.sync() function:

    const synced = await account.sync()
    console.log('available balance', account.balance().available)

    const address = 'atoi1qykf7rrdjzhgynfkw6z7360avhaaywf5a4vtyvvk6a06gcv5y7sksu7n5cs'

    // TODO: Check if address is valid.

    const amount = 1000000 // Amount in IOTA: 1000000 == 1 MIOTA

    const node_response = await synced.send(

    console.log("Check your message on https://explorer.iota.org/chrysalis/message/", node_response.id)

The full function signature is SyncedAccount.send(address, amount[, options]).

Default options are perfectly fine and get the job done; however, additional options can be provided, such as remainderValueStrategy:

  • changeAddress: Send the remainder value to an internal address
  • reuseAddress: Send the remainder value back to its original address

The SyncedAccount.send() function returns a wallet message that fully describes the given transaction. The messageId can be used later for checking a confirmation status. Individual messages related to the given account can be obtained via account.listMessages() function.

Please note that when sending tokens, a dust protection mechanism should be considered.

Chrysalis Migration

With the advent of the Chrysalis migration, a number of aspects at IOTA are changing for the better. With easier ways to manage and secure your experience, IOTA will seamlessly integrate these innovations with no service interruptions.

With Chrysalis, we make a clear-cut from the current IOTA protocol, and start a new with a much better, and more mature network. The new network will support many new use cases and create a foundation for IOTA’s upcoming Coordicide.

This includes one of the innovations that directly impacts one of the most crucial aspects of your experience: funds.

Because of its complexity, the migration process for the next phase of Chrysalis consists of two phases; we are currently in phase one where you initiate the migration of your funds in one week and which will then be available on our new network upon launch.

Do note that migrating is a continuous effort that can be done at any time after the initial migration start date.

Token Migration Overview

Below is an overview of how the migration will take place for normal token holders:

  • You enter your seed in Firefly.
  • Firefly creates you a new seed and generates an EdDSA address for the new network.
  • Firefly sends your funds to a specific migration address (which encapsulates your EdDSA address) on the old network.
  • Your funds become available on the new network on the EdDSA address Firefly created for you.
  • Your funds are successfully migrated.

Note that:

  • If you migrate before the Chrysalis launch, your funds become available at Chrysalis launch.
  • If you migrate after the Chrysalis launch, your funds will become available shortly after you migrate (within less than 5 minutes).

Firefly will initially only be available on desktop operating systems such as: macOS, Linux and Windows and not support migrations for Ledger devices or using a Ledger device.

For further information on the migration process, see our blog post.

For a detailed explainer on how the migration process works technically, see migration-mechanism

Exchange Token Migration Guide

To help you successfully transfer your tokens securely to the new Chrysalis (IOTA 1.5) network, we created this guide as an overview of the migration process and its intricacies.

Following dates are important to be aware of:

  • From 21st to 28th of April, token holders are able to pre-migrate their funds. During this period the network has no limitations and runs as it would normally. Migrating funds during this period effectively locks them up to become available immediately on the 28th of April after the Chrysalis Phase 2 release.
  • On the 28th of April, Chrysalis Phase 2 gets released (with its corresponding node software, libraries and tooling). After that, the legacy network will only support migration transfers going further (this is accompanied by a legacy node release). This means that both a legacy (albeit only for migrations), and a new Chrysalis Phase 2 network will co-exist. We therefore suggest stopping withdrawals and deposits some time before the 28th of April, to ensure that no funds are being sent from/to the exchange (since any non migration transfers will no longer confirm).

There are two ways with which you can migrate your funds from the old legacy to new Chrysalis Phase 2 network:

  1. You can either use our Firefly wallet (which allows migrating from either an 81-tryte seed or seed vault file). (Check out this blog post on how to do this).
  2. Or you can craft a migration bundle yourself which transfers your funds to a special migration address under your control (programmatic approach).

Note that if you migrate your funds after the 28th of April, they will become available on the new network within 5 minutes. If you migrate prior to that, your funds will only become available starting on the 28th of April.

This guide will further only explain how to create a migration bundle, and the rules imposed on it.

Migrating funds by issuing migration bundles

Note that as mentioned above, there will be a special release for the legacy node software on the 28th of April, which will only further support migration bundles. In case you're operating a node yourself you must upgrade to that version, as otherwise you will no longer be synchronized with the network.

Migration bundle

With this limited legacy network, only migration bundles will further confirm. A migration bundle is nothing else than a normal value bundle/transfer which has some additional restrictions. If you craft a bundle which obeys to the following rules, then it falls under what we define as a migration bundle:

  • It contains exactly one output transaction of which the destination address is a valid migration address and is positioned as the tail transaction within the bundle (meaning currentIndex 0). The output transaction value is at least 1'000'000 tokens (1 Mi).
  • It does not contain any zero-value transactions which do not hold signature fragments. This means that transactions other than the tail transaction must always be part of an input.
  • Input transactions must not use migration addresses.

If in doubt whether your bundle is an actual migration bundle, you can use ValidBundle(bundle, true) function of our iota.go library to validate this. In case you're not acquainted with Go, you can also contact us on Discord or Slack in order to get the assurance, that you're crafted bundles are valid migration bundles.

Things to consider:

  • You must not broadcast your own migration bundles unless you're 100% sure that they are indeed valid migration bundles.
  • If one of your input transactions spends funds from an already used address (meaning it is subject to key re-use), we recommend that you use the bundle miner tool to craft a bundle with the most applicable security given the already exposed parts of the given address' private key.
  • Do not use too many input transactions as this will increase the overall Proof-of-Work time needed for a single bundle. Rather, split your input addresses over multiple migration bundles.
  • Your code must include logic to await for the migration bundle's confirmation. If you find that your migration bundle is not confirming, consider re-attaching it (re-attaching is not the same as re-signing the bundle!).
  • If you submit a migration bundle for broadcasting via the broadcastTransactions API command and you're using the updated legacy node software (which you must on/after the 28th of April), then it will additionally check up on submission whether your submitted bundle really adheres to the rules outlined above as an additional safe guard.

For further information about the migration bundles, have a look at RFC-0035 .

As an example, this bundle is a valid migration bundle. It spends 1 Mi

  • to: TRANSFERTBIXPEWWYZZWBWPWJCB9XYMC9AGYH9X9AYAYADVXTYGYB9G9J9PEF9O9KYZXS9D9MANWTZOD9B9HMRQFWZ where the destination address encodes the target Bech32 address iota1qqhmslysuwfedz2mqtr4ux73pr7uhjmd4tpazqs8pf7qdax44muqgw0fz25 respectively the hex Ed25519 address 2fb87c90e39396895b02c75e1bd108fdcbcb6daac3d102070a7c06f4d5aef804 on which the these funds will be made available in the new network.
Migration Address

As mentioned above, a migration bundle must have as its single destination/output address a migration address. A migration address is in essence an EdDSA address (to which you hold the keys on the new network) encoded in a legacy tryte address. You can create such an address in the following way:

  • Compute the BLAKE2b-256 hash H of your Ed25519 address A (this address is the one you control in the new network; note that an Ed25519 address is the Blake2b-256 hash of your Ed25519 public key).
  • Append the first 4 bytes of H to A, resulting in 36 bytes.
  • Convert A to trytes using the b1t6 encoding (as described in RFC-15) . This results in Atri consisting of 72 trytes.
  • Prepend the 8-tryte prefix TRANSFER to Atri.
  • Finally, pad Atri with the single tryte 9 to get a legacy 81-tryte address.


  • Ed25519 address (32-byte): 6f9e8510b88b0ea4fbc684df90ba310540370a0403067b22cef4971fec3e8bb8

Since nobody holds keys to such migration addresses, funds are effectively burned and can no longer be used in the legacy network.

How the IOTA Chrysalis Phase 2 Token Migration works

For the transition to Chrysalis Phase 2, the IOTA Foundation had to develop a way for funds to be migrated to this new network. The reason a migration mechanism needs to exist in the first place, is because the new network no longer supports WOTS addresses (currently all funds in the legacy network reside on these).

The developed mechanism features following properties:

  • It is trustless, meaning that everyone who's interested can verify that migrated funds are indeed legit and are not minted out of thin air.
  • Migrated funds take less than 5 minutes until they become available in the new network.
  • Migrations can take place any time for the foreseeable future.

Before going into the actual developed mechanism, lets see why other mechanisms were not chosen:

  • Migrating funds by performing periodic global snapshots on both networks: While this approach certainly would have been the easiest to do, it would have blocked funds of people between the times of global snapshots. For example, if we would have taken global snapshots monthly (to carry over funds from burn/migration addresses), token holders would have been excluded from opportunities arising from the change in token price: i.e., perhaps you wanted to sell your tokens but were blocked by the fact that the next global snapshot would only be performed in 20 days and so you couldn't move your tokens to an exchange (which only supports Chrysalis Phase 2 IOTA).
  • Supporting WOTS on Chrysalis Phase 2 (and only allowing to send to non WOTS addresses): While certainly also a viable option, we decided to not include support for WOTS as it brings a number of legacy problems we want to get rid of:
    • WOTS signatures are very large and make up a disproportional amount of data in a transaction (note that our PoW requirement in Chrysalis Phase 2 is dependent on the size of the message). Additionally, there were no real bounds on how big such signatures could grow to (even if per default we only supported 3 security levels in our libraries).
    • We would have needed to pollute our new Chrysalis Phase 2 models with support for these addresses and signatures, adding unnecessary complexity to what should be a clean protocol.
    • Chrysalis Phase 2 nodes would have needed to keep a spent address list to inform wallets that they had vulernable addresses.


The developed migration mechanism is built from following components:

  • Chrysalis phase 2 data types ( see the RFC for details):
    • Treasury Output: an object which specifies an amount of tokens held in the treasury.
    • Treasury Input: an object which references a previous Treasury Output.
    • Treasury Transaction: an object which defines a Treasury Input referencing the last Treasury Output and a new Treasury Output holding the delta of what the Treasury Transaction is spending.
    • Receipt: an object which holds a pointer to a legacy milestone index, a list of funds to mint and a Treasury Transaction. A Receipt can only be an inner payload of a milestone.
  • Chrysalis Phase 2 nodes which validate receipts
  • Legacy nodes which provide a special API command for the above Chrysalis Phase 2 nodes
  • Treasury: this is simply the last Treasury Output in the ledger. There exists only ever one at any point in time. When the Chrysalis Phase 2 network launches, the Treasury contains the total supply of tokens (2779530283277761) minus the funds which were already migrated during the "7-day-migration-period" prior to the network launch. This means that all funds which are not migrated from the legacy network, always will reside in the Treasury .

Note, that again, a Receipt can only be contained within a milestone and that valid milestones can only be issued by the Coordinator, therefore, minting of migrated funds can only happen through milestones and not any other type of transactions. Likewise, a Treasury Transaction is only valid to be an inner payload of a Receipt.

How it actually works

  1. In essence, a Receipt carries the information about funds which were migrated or "burned" to a migration address on the legacy network. A migration address looks like any other normal address on the legacy network but it encapsulates actual information, such as:
    • The target Ed25519 address on the Chrysalis Phase 2 network from which the token holder wants their funds to be accessible from.
    • A checksum of that Ed25519 address.
    • A tryte prefix TRANSFER. (these addresses always start with this prefix)
  2. As mentioned above, a Receipt can only be contained in a milestone and therefore the Coordinator on the Chrysalis Phase 2 network:
    1. periodically polls data from a legacy node about what kind of newly confirmed burned/migrated funds there are ( while also performing WOTS signature verification on these and the legacy milestone bundle).
    2. and then produces a milestone with a Receipt containing those funds, where within the Receipt, a Treasury Transaction is placed which deducts the sum of tokens migrated from the Treasury.
  3. Chrysalis Phase 2 nodes then see receipts when applying milestones and automatically generate outputs for the Ed25519 address as defined in the origin migration address in the legacy network. As an optional step (which is not turned on by default), every node can be configured to verify whether the funds in the receipt really were migrated in the old network using a legacy node and whether all funds for a given legacy milestone index were migrated. If this verification fails, the node will automatically panic as the integrity is no longer correct.

This means that:

  • The IOTA Foundation can not mint funds out of thin air, because nodes in the Chrysalis Phase 2 network verify that the funds were burned in the legacy network.
  • All migration bundles, respectively transfers to migration addresses which were confirmed by a given legacy milestone, must be migrated fully to the new network, as otherwise the verification fails.
  • Node operators are free to choose which legacy nodes they query with their Chrysalis Phase 2 nodes, so the verification of migrations/receipts is decentralized. For example, a node operator chooses to both operate their own legacy and Chrysalis Phase 2 nodes.

Essentially then via the Firefly wallet, token holders will:

  1. Produce migration bundles which send funds to migration addresses controlled by the given owner.
  2. These bundles get confirmed on the legacy network.
  3. The Chrysalis Phase 2 Coordinator picks these confirmed legacy bundles up and generates receipts minting those funds to the target Ed25519 address.
  4. Verifier nodes verify the receipts and make sure that the funds originate from the legacy network.

Verifier node

A verifier node is a Chrysalis Phase 2 node which up on seeing receipts:

  1. Queries a legacy node for the confirmation data for the specified milestone in the receipt.
  2. Then performs WOTS signature verification of the legacy milestone bundle and all confirmed bundles.
  3. Additionally it also checks that all confirmed funds on the legacy network for the given legacy milestone, are indeed minted with a given batch of receipts. (i.e. nothing is left out)

See Hornet as a verifier node

IOTA Hub migration guide

This guide will explain how you can switch from IOTA Hub to using wallet.rs or its bindings instead.

Because of the unique features of IOTA 1.0, it was difficult to manage IOTA transactions with just a library. With the new Chrysalis update, the whole protocol was updated to be more accommodating to industry wide standards and developer friendliness.

IOTA Hub will be deprecated with the Chrysalis upgrade and will not work with the new protocol changes. If you still use Hub, we ask you to utilize our new wallet library (iota.rs or bindings) where you can easily manage IOTA addresses, deposits, and withdrawals for user accounts.

To upgrade from Hub to a Chrysalis implementation you need to:

  • Integrate the Chrysalis network using wallet.rs as mentioned in the Exchange section
  • Pause withdrawals/deposits
  • Make sure all balances have been swept and all deposits have been processed
  • Transfer all IOTA to a generated migration address (instructions to be provided)
  • Once migrated, transfer the IOTA coins to your hot wallet account on your wallet.rs implementation

Backup and security

Security Checklist

  • How to backup your account
  • How to restore from a backup
  • How to export a user's Stronghold
  • How to rekey a Stronghold/password rotation
  • Do's and don'ts

Security checklist

  • I use Stronghold
  • I use a strong password (32 character length, Shannon Entropy ~ 4.0) for encrypting the stronghold
  • I rotate the stronghold password on a regular basis
  • I create a daily backup of the stronghold.snapshot file
  • I keep a secure history of passwords used (for recovery)
  • I use a secure password management service that integrates with the server
  • I use a linux based server (best memory security)
  • My server is isolated behind a DMZ

How to backup your account

A simple copy of the stronghold.snapshot file works as a backup (e.g. a daily cronjob rsync/scp with a datetime suffix for example).

How to restore from a backup

Simply place a snapshot file in your directory that wallet.rs expects.

How to export a user's stronghold

You can create a new Stronghold snapshot on the fly to allow a user to leave your service and retain their key.

How to rekey a Stronghold/password rotation

The procedure for changing a Stronghold password is "simple" in that you read a snapshot into a vault and then write it out with a new encryption password. See this code for the source.

Please note: for obvious reasons, old snapshot backups will not be "rekeyed", so you have to track your old passwords.

Do's and don'ts

  • Don't use SQLite
  • Don't store passwords and backups on the same device

Chrysalis Snapshot Validation/Boostrapping

In this guide you will learn how to partake in the global snapshot, respectively genesis snapshot creation for the legacy and Chrysalis Phase 2 IOTA network. The goal is to generate a global snapshot for the legacy network which acts as a cut-off point for when only migration bundles/transactions are allowed, and a genesis snapshot for the new network which contains the already burned/migrated funds from the 7-day-migration window.


  • A GitHub account and git
  • A synchronized legacy Hornet node (running version < 0.x.x)
    • The getLedgerState API command must be permitted. Add an entry to httpAPI.permitRemoteAccess in case this API command is not added yet (restart your node afterwards).
    • The API port must be accessible
  • Golang version 1.16.x (https://golang.org/)


Make sure you've Go installed by issuing go version on your command line.

  1. git clone https://github.com/iotaledger/chrysalis-tools.git
  2. cd chrysalis-tools/snapshot/verify
  3. go build (this should generate a verify/verify.exe binary respectively)
  4. ./verify -node="https://your-node-uri" -genesis-snapshot-file-network-id="chrysalis-mainnet" -genesis-snapshot-file-network-id-alt="as-network"
  5. The program will now fetch the current ledger state of your defined legacy Hornet node, compute its Blake2b-256 hash and generate the global snapshot for the legacy and genesis snapshot for the new network. Example output:
2021/04/28 12:05:22 querying legacy node for info...
2021/04/28 12:05:22 legacy node state: lsmi/lsm 3705194/3705194
2021/04/28 12:05:22 fetching ledger state at 3705194, this might take a while...go grab a coffee...
2021/04/28 12:05:27 total ledger entries: 340692
2021/04/28 12:05:29 legacy ledger state integrity hash: 8900ac80edffe4eed9f6f55dfe32d775c18d789351c7dddfa4a4c815a0fa7116
2021/04/28 12:05:29 migration: addrs count 7949, tokens total 661557732260355
2021/04/28 12:05:29 migration (alternative): addrs count 7950, tokens total 724118708261378
2021/04/28 12:05:29 generating genesis snapshot files...
2021/04/28 12:05:29 treasury allocation with genesis_snapshot.bin: 2117972551017406 tokens
2021/04/28 12:05:29 treasury allocation with genesis_snapshot_alt.bin: 2055411575016383 tokens
2021/04/28 12:05:29 misc info:
2021/04/28 12:05:29 eligible for migration: addrs 225329, tokens total 2055405216227457
  1. Generate the sha256 hashes of the generated snapshot files: sha256sum genesis_snapshot.bin genesis_snapshot_alt.bin global_snapshot.csv ; Example output:
$ sha256sum genesis_snapshot.bin genesis_snapshot_alt.bin global_snapshot.csv 
65be1a80a6895d17a492db3dd55babf1d57557dbaa40da6e1d0ed5937ceb6662  genesis_snapshot.bin
39bd5308a1e9fb57503f6d15b90206ae434f581807ef0e29cf2e66de64165c5b  genesis_snapshot_alt.bin
8f48388423cc706bf5f7707735fd99a5d89efbb966a8e2a0b82ff3529cf33f7f  global_snapshot.csv
  1. Copy the entire program output, and the sha256 hashes to the corresponding issue on the iotaledger Hornet fork repository.

Bootstrapping the legacy Hornet node from the global snapshot

Loading the global snapshot ensures that your legacy Hornet node adds the genesis transaction (999...) as a solid entry point: this is important as the Coordinator will issue the next milestone after the global snapshot index on top of it. Your node will not lose the data it already has.

  1. Await for confirmation that the global snapshot was taken successfully by looking into the validation issue on the Hornet repository or Discord.
  2. Stop your legacy Hornet node and download the binary or docker image of the Hornet build which only supports migration-bundles. With this "migration-bundles-only" version, your Hornet node will also no longer peer to nodes which do not run the same version.
  3. Let snapshots.global.path point to the global snapshot file (i.e global_snapshot.csv).
  4. Under snapshots.global.index define the index of the milestone at which the global snapshot was taken. (this should correspond to what legacy node state was from the program output, i.e. 3705194 from the example output above).
  5. Change snapshots.loadType to "global" (note the quotes as the value is a string).
  6. Restart your legacy Hornet with the additional --forceGlobalSnapshot flag (this will instruct your Hornet node to load the global snapshot despite the fact that it already has a database).


Public Infrastructure

The IOTA Foundation provides following loadbalanced public mainnet endpoints:

  • chrysalis-nodes.iota.org
  • chrysalis-nodes.iota.cafe

These endpoints have MQTT (via WebSockets) exposed and offer the HTTP REST API (according to this specification) over TLS.

Developer tools


Public Infrastructure

The IOTA Foundation provides the following loadbalanced public testnet endpoint:

  • api.lb-0.testnet.chrysalis2.com

We recommend using the load balancer for most scenarios.

Single node endpoints that expose native MQTT, in case you need them, are:

  • api.hornet-0.testnet.chrysalis2.com
  • api.hornet-1.testnet.chrysalis2.com
  • api.hornet-2.testnet.chrysalis2.com
  • api.hornet-3.testnet.chrysalis2.com

These endpoints have MQTT (via WebSockets and raw TCP) exposed and offer the HTTP REST API (according to this specification) over TLS.

Developer tools

IOTA Protocol RFCs

Changes to the IOTA protocol have to go through a proposal process first, where a proposal is posted as a "Request for comment" (RFC). The Chrysalis protocol changes are described in full detail in these RFC's which can be found below:


Official support

IOTA Explorer


Official Tangle explorer with a lot of tools to browse through the Tangle.



The official Discord server where community members and the IOTA Foundation discuss projects and related subjects.

IOTA StackExchange


The official forum where you can ask or answer technical questions about IOTA.

Community support

TheTangle.org - IOTA Explorer


A community tool for searching transactions in the Tangle.

TangleExplorer - IOTA Explorer


An community tool for searching transactions in the Tangle.


Which libraries are available for Chrysalis?

At this time, there are a handful of libraries available for Chrysalis which are outlined below:

A low level library called iota.rs which is a client library meant to connect to a IOTA node for core interactions with the Tangle. It is written in Rust and there are currently two bindings for Node.js and Python allowing you to use this library from those languages as well.

For value transactions, there is the wallet.rs library which provides a stateful way to manage IOTA coins for one or multiple accounts. It is also written in Rust and there are currently two bindings for Node.js and Python.

Additionally, there is also a native C (iota.c) and an alternative, native javascript (iota.js) client library.

What is Dust protection and how does it work?

Since IOTA is feeless and has the ability to send microtransactions, attackers could use this to spam the network with very low value transactions, which we call dust. To avoid this we only allow microtransaction below 1Mi of IOTA tokens to another address if you already have at least 1Mi on that address.

You can read more about Dust Protection in the RFC here.

What's happening with Coordicide?

This release called Chrysalis still depends on the Coordinator/Compass to run and issue milestones. The next big release after Chrysalis will be Coordicide where we get rid of that dependency. This release is currently in a research/testing phase and will be the main priority after the Chrysalis release.

When is a transaction on the network considered final/irreversible?

Confirmation times on the new network are on average around 10 seconds. Once a transaction is set to confirm it’s final transaction, you don’t have block confirmations like with blockchain.

Hornet or Bee? Which node software should I use?

You can pick either Bee (Rust based) or Hornet (Go based). We currently recommend Hornet since it’s the more complete version of the node software, Bee is still missing some optional features you might wish to use.

What are spent addresses and why are they dangerous?

  • In the IOTA 1.0 network, IOTA used Winternitz One Time Signatures (W-OTS) - think of these as, more or less, an authenticator and validator for a transaction. These keys and signatures are highly secure against malicious attacks for signing transactions. But, on the downside, by signing a transaction, W-OTS reveals parts of a private key for the specific address tokens are being spent from.
  • With W-OTS every time a signature is signed to spend tokens from a particular address, any remaining tokens need to be moved onto a new address to prevent malicious actors from brute-forcing (trial-and-error guessing) the remaining parts of the private key for the address. That’s the main reason why this signature scheme is considered to be a “one-time signature”.
  • So after the Chrysalis update, we are using the Ed25519, based on the EdDSA, scheme instead of W-OTS. The advantage is that the new scheme addresses all of the issues that W-OTS originally had, where Ed25519 verifies both single-signature and batch verification (taking care of the left over/remaining tokens) very quickly as well as faster key generation and smaller signatures (very secure).

What is bundle mining?

  • If you have spent addresses, it means you accidentally received funds to an address that was already spent from and these funds are not safe to send again due to W-OTS.
  • To secure your spent addresses during the migration, Firefly will try to find a new bundle that reveals the least amount of additional private key parts compared to previous signs.
  • This process will take 10 minutes per spent address and upon completion you will be presented with a risk calculation (very high, high, medium, low, very low). It is recommended that you repeats the process if it returns a bundle with medium risk or higher, particularly for significant sums of IOTA. You have the option to select which addresses you want to mine for and again which you want to rerun the process for.