Arbitrum Orbit chain migration to Espresso
Espresso Nitro Integration
You may wish to familiarize yourself with the security audits for this integration.
The target audience for this document are developers who would like to migrate an existing Arbitrum Orbit chain to use Espresso's Global Confirmation Layer (GCL). The document should also be interesting for developers who are thinking of deploying a new Arbitrum Orbit chain that uses Espresso's GCL.
The goal of this document is to describe how to migrate an Arbitrum Orbit chain to using Espresso's global confirmation layer for fast confirmations. By leveraging Espresso's fast confirmations, a rollup will only accept a batch after it has been finalized by Espresso. This integration ensures that each batch processed by the rollup is consistent with HotShot-finalized blocks within its namespace.
Quickstart
The quickest way to get familiar with what the migration entails is to run through our migration test.
The script creates up an ephemeral Nitro chain on the local computer and migrates it to using Espresso's Global Confirmation Layer (also running locally on the computer). This test mocks out the TEE part by using a mocked TEE verifier contract and configured the batch poster to bypass the TEE interactions. Thereby it's possible to run through the migration locally, without requiring a special CPU and extra software to support the TEE.
For a safe production deployment the TEE is required and the real TEE verifier contract must be deployed.
The test requires Docker, Foundry, Yarn, openssl
and jq
to be installed.
For convenience the nix package manager can take care of installing all dependencies except for Docker. Nix can be installed by running
To run the test first some setup:
Now you can run the test itself.
You should see substantial output. After some time, if successful, you should see Migration successfully completed!. It's encouraged to read through the migration test to get an idea of all the steps involved and what information is required for each step. For the real migration using .env
files instead of environment variables to provide the necessary inputs may be more convenient.
Once familiar, you might run some commands to further your understanding. Transfer some eth, for example:
Assumptions
Before attempting a migration please verify that the assumptions listed here make sense for your nitro deployment. If not, please get in touch with us via our contact form.
The Orbit chain to be migrated is using vanilla Nitro stack, or Celestia DA via the Celestia fork of nitro. If your Orbit chain is using Celestia for DA you need to use the
celestia-integration
branches of Espresso's nitro forks.You are able to run the batch poster in an SGX TEE environment. This is required to provide TEE attestations that the L2 transactions have been finalized by Espresso. These attestations are verified in the TEE verifier smart contract on the parent chain as part of the batch submission.
Requirements
There are are some system prerequisites needed to perform the migration:
SGX
Gramine
You will also need these Espresso projects. Depending on whether you use celestia DA or not, you will need either the integration
branch or celestia-integration
branch. Please take the time to review each project's respective README.
As well as Espresso’s nitro-node docker image:
Migration Flow
This flow is more precisely defined in our migration test. Since that script is intended for testing migrations, it does not not require SGX. Therefore it should not be use for production deployments.
Run the new batch poster inside SGX and get the
MREnclave
andMRSigner
values (which is the hash of the code running inside the SGX). These values are needed to deploy the EspressoTEEVerifier contract.Deploy the
EspressoTEEVerifier
contract.Stop Nitro node with the batch poster and copy the batch poster’s databases files to the TEE.
Perform the sequencer inbox migration.
Run new Batch poster. You will notice it starts catching up messages and building up state.
Please also be aware of steps to revert a migration should you need them.
Verify SGX Setup
Setup of SGX TEE is beyond the scope of this document. We have had success with Azure SGX VMs
First verify you have linux version with in-kernel SGX. To ensure you have in-kernel SGX run the following command to verify you are running a Linux kernel greater than version 5.11
.
Ensure that your machine has an Intel SGX2 (Software Guard Extensions) enabled CPU to run our batch poster (See here and here). You can verify if your CPU supports SGX2 on Linux by inspecting CPU information:
If your CPU supports SGX, the output should resemble the following. If it does not, your CPU either doesn't support SGX2, or it isn't enabled in the BIOS.
Install Gramine
To install gramine follow the following instructions:
Install software packages
Setup host configuration
Install the SGX software stack
If your machine is running on Microsoft Azure, you can refer to this document for configuring aesm.
You don't need to follow the build gramine steps as we will be using Gramine Shielded Containers (GSC)
At this point systemctl status aesmd
should report a healthy service (Active: active (running)).
If you see any errors here, ensure your aesmd
is configured properly. If your machine is running on Microsoft Azure, you can refer to this document for configuring aesm
.
Running the Batch Poster Inside SGX
Building the Poster Image
These steps need to happen inside SGX
Use our default Dockerfile.sgx-poster
or the Celestia Dockerfile.sgx-poster
to build the sgx-poster Docker image.
First obtain the source:
Alternative 1: using default Nitro stack
Alternative 2: using Celestia DA
Then build the image.
Building the Gramine Image
Once the docker image is built, you need to build a Gramine Shielded Container (GSC) image.
The gsc
python script requires a few python packages. For ubuntu 24.04 run
For more information see the GSC docs.
Clone Espresso's gsc
repo and build the Gramine image:
Now before building the gramine image, you need to edit your poster_config.json
file to include the following fields (given parent chain is arbitrum sepolia):
You need the sha256 hash of your poster_config.json file. You can get the hash using the following command:
Replace the nitro-espresso.manifest
in the gsc with these contents and replace the <YOUR_SHA256_HERE>
with the sha256 of your poster_config.json file.
Next we will need to sign the image in order to run this container inside the SGX enclave.
Generate the signing key (if you don’t already have one).
PLEASE KEEP THIS KEY SAFE in some local private storage, but delete it from the server after you have signed.
Sign the container
The final step is to run the container inside the SGX enclave. This requires a config
folder which contains the poster_config.json
file (available from the legacy batch poster).
Finally we also need a .arbitrum
folder which contains the state of the batch poster. At this point it can be an empty folder but once the legacy batch poster is shut down, we should fill this up with the contents of the legacy batch poster and re-start the poster.
Run the batch poster using the following command, replacing $CONFIG_PATH
with the actual path to these folders on your host machine.
These folders are mounted in the docker container, so any changes to them on the host change them in the container.
At this stage, you will see an attestation report similar to the following. The hex value, is the report data which contains the MR_ENCLAVE
(the hash of the code running inside SGX) and the MR_SIGNER
. After you see the attestation report, you can shut down the batch poster.
You can decode all this information using the following steps:
Create a
report.txt
file with the hex value and create a bin file as follows:Use this bash script to decode the binary, it will print out the
MR_ENCLAVE
andMR_SIGNER
.
Deploying the EspressoTEEVerifier
contract
EspressoTEEVerifier
contractContract Deployment
You will need to use our version of nitro contracts. The instructions below assume you are using celestia for DA. If not, simply checkout on integration
branch instead.
Please clone this repo at the given branch to follow the next steps.
To run this script to deploy a rollup on arbSepolia follow the given steps:
Compile the contracts using yarn
Create a .env
file with variables from the previous steps
Deploy the contract
Sequencer Inbox Migration
Obtain the Contracts
In this section we will be working out of our orbit-actions
repo. Again the choice of integration
or celestia-integration
depends on DA.
Be aware that the contract to deploy the sequencer inbox needs to locally deploy a mock ArbitrumChecker to prevent foundry from declaring calls to precompiles as invalid opcodes. This shouldn’t affect on chain deployment from these scripts, nor should it affect the onchain execution of the migration action.
Configuration
Create a .env
file in the orbit-actions directory that contains the following values:
Source it.
Install all dependencies.
Run the migration deployment scripts
Run the migration deployment scripts for the parent chain. Including both DeployAndInitEspressoSequencerInbox.s.sol
, and DeployEspressoSequencerInboxMigrationAction.s.sol
. From the base directory of the orbit actions repo, you can use the following commands to run these scripts:
DeployAndInitEspressoSequencerInbox.s.sol
Before you proceed: make sure to store the address of the new SequencerInbox in the environment variable NEW_SEQUENCER_INBOX_IMPL_ADDRESS
DeployEspressoSequencerInboxMigrationAction.s.sol
Before you proceed: make sure to store the address of the new SequencerInbox in the environment variable SEQUENCER_MIGRATION_ACTION
Execute the Upgrade
The final step for executing the migration involves using cast to call the perform()
function of the sequencer inbox migration action via the upgrade executor. You can use the following command to accomplish this:
After running this command, your rollup contracts should be set up to accept batches from your new batch poster.
Run the Batch Poster with Legacy State
As stated in upstream documentation, you need to copy the contents of the .arbitrum
folder of the legacy batch poster to the .arbitrum
folder of the new
Then re-start the batch poster.
Verify the Migration
You should be able to see batch sent
logs once the batcher starts posting batches. This would indicate that the batcher has started successfully.
Last updated