Architectural overview

Nightfall's main components

Nightfall's containers

Nightfall, as an application, comprises a set of Smart Contracts deployed to the blockchain and a number of docker containers that mediate interactions between the blockchain and the actors described on the last page. This group of containers is referred to as a Nightfall node. Note that Nightfall requires access to an RPC endpoint of a conventional Ethereum node so that it can listen to the blockchain. Also note that a Nightfall node does not send transactions to the blockchain. It just listens to blockchain events. Instead, it creates ready-to-sign Ethereum transactions and sends them over its API for an auxiliary application to sign and send to the blockchain. This is so that it does not need to hold an Ethereum private key. It is the job of the auxiliary application to manage the security of Ethereum keys. There could be up to four auxiliary applications (one for each actor) depending on the services that the Nightfall node in question is providing. The Nightfall_3 repository provides basic auxiliary applications that will work for many use cases.

The containers associated with a Nightfall node and their interactions are shown below:

If Nightfall is started using its Docker Compose script (not recommended for production but otherwise very handy) Nightfall will also fire up an http server, an admin container, a mongo database and a rabbit MQ container. These may or may not be used, depending on your configuration (more on this later). The functions of the containers are as follows:

  • client: This exposes http APIs that are useful to the User. These are used for making Deposits (moving funds into Nightfall's Layer 2 from an ERC20, 721 or 1155 contract), Transfers (moving funds privately within layer 2) and doing Withdrawals (moving funds out of Nightfall and back into and ERCx contract). There are also APIs for interacting with Nightfall Native Tokens but that is covered elsewhere. Additionally there are APIs to assist with operation (for example generation of ZKP keys).

  • worker: When a User requests a Nightfall transaction, Client will prepare an unsigned Ethereum transaction, which will enact the requested Nightfall transaction, for the User to sign and send to the blockchain. Part of preparing that transaction is the generation of a Zero Knowledge Proof (ZKP). This is handed off to a Worker container for reasons of scalability: ZKP generation is compute and memory intensive, and it may be required that several Workers are instantiated to support a single Client. In such a circumstance, the Rabbit MQ container can share the work amongst multiple Workers. Each Worker is really just a containerisation of Circom binaries and http://, mqtt:// APIs/

  • optimist: This container exposes APIs (http:// and ws://) which are useful for Proposers and Challengers. It outputs unsigned Ethereum transactions for the creating of Nightfall Layer 2 blocks. It also monitors the posting of new Layer 2 blocks to the blockchain and in the event of a bad block, creates a challenge transaction for the connected Challenger to send in to the blockchain. This container is therefore responsible for the correct operation of Nightfall's Optimistic layer.

  • deployer: This is an ephemeral container, only useful for deployment of Nightfall. It will perform a trusted setup, if one does not already exist (note: this will be an insecure trusted setup, only suitable for test purposes) and will deploy Nightfall's smart contracts, if these are not already deployed.

Nightfall's volumes

As well as the containers, Nightfall uses several volumes to persist data. These are mounted into relevant containers. When using a simple Docker Compose deployment they are Docker volumes but they can be other types of volume (e.g. AWS NFS) depending on the deployment environment. The Deployer container will create and populate these volumes if they do not already exist:

  • proving_files: This contains the ZKP circuits and corresponding zkeys required to generate Zero Knowledge Proofs. It is mounted by the Worker containers.

  • .openzeppelin: Nightfall has the capability to upgrade its deployed contracts via a multisig contract, using Openzeppelin Upgrades, although in our current deployments this is disabled by configuring the multisig with approval addresses that don't have known private keys. This volume still exists however and contains contract address metadata. It is mounted by Deployer.

  • build: This contains contract metadata (addresses and APIs), which enable the containerised Nightfall applications to interact with the on-chain smart contracts. It is mounted by Client and Optimist.

  • mongodb: This is the storage for the MongoDB container. In most production scenarios, a Mongo instance will already exist and will be used instead of the Nightfall-provided MongoDB container


Something has to call Nightfalls APIs and something has to sign the Ethereum transactions that Nightfall creates. These are the Nightfall apps. They may themselves be containerised, or they may run natively. Generally, these will be created by the organisation running a Nightfall node and will be specific to their business needs, particularly in the case of a User application. For this reason, Nightfall does not provide a User application, other than a simple GUI for demo purposes, however it does provide an Nf3 class, which provides a nodejs API to simplify creation of a User application. Nf3 has the same relation to Nightfall that web3js or ethers.js have to an Ethereum node.

For the Proposer and Challenger apps, the Nightfall repo contains simple implementations, which will be useful for a number of situations. Both of these make use of the Nf3 class. Nightfall's integration tests are also examples of how to interact with Nightfall. It would of course be possible to integrate these implementations into the Optimist container, and this may be done in the future. One advantage of a separate application, though, is that Optimist does not have to hold Ethereum signing keys, and this separation of security concerns may be useful.

  • challenger: This listens to an Optimist websocket for challenge transactions. When it receives a challenge transaction, it signs it and sends it to the blockchain, implementing a challenge (in practice it's a little more complex because of the need to prevent front running but we'll explain that detail elsewhere).

  • proposer: This listens to an Optimist websocket for Layer2 block proposal transactions. It signs these and sends them to the blockchain. It can also receive transactions directly from a User and proxy these to the Optimist for inclusion in a Layer 2 block. This is sometimes useful because it means that Optimist does not have to be exposed to the internet.

  • Liquidity provider [ToDo]

Other Nightfall containers

Nightfall may implement other containers in certain circumstances. These are not always required however:

  • rabbitMQ: This can be placed between a Client and multiple Workers to share out proof generation across the Worker instances. In a basic configuration Client makes an http:// request directly to a single worker and RabbitMQ is not used.

  • administrator: This container runs a command line API, which can be used to interact with the functions in Nightfall's smart contracts which are only callable by the contract owner (onlyOwner modifier). All current Nightfall deployments are completely decentralised and so these functions are not callable.

  • mongodb: Most production implementations will provide a Mongo instance. In this case the Nightfall containers can be pointed at the existing instance and will use it to persist Nightfall data (e.g. Merkle tree data, commitments and nullifiers, blocks, transactions...). In other situations, this container can be used and it is the default for Nightfall instances deployed using the Docker Compose scripts.

  • hosted-utils-api-server: This container is used to serve html for a web-based Nightfall wallet (for test purposes). The wallet is no longer supported but this container is retained in case another organisation wishes to support the wallet.

Last updated