Chapter 29
Arbitrum Nitro Sequencer Inbox

Requirements: Nitro Integration Requirements


Contents



29.1 Overview
29.1.1 AddSequencerL2Batch
29.1.2 AddSequencerL2BatchFromBlobs



29.1 # Overview

This page contains technical details of the SequencerInbox.sol contract used by the Nitro integration

The only qualification for calling this function is having a valid TEE attestation; that is, the key must be generated by a batcher running the appropriate code. This allows anyone running the right code to become a batcher, satisfying the Permissionless Batching requirement.

29.1.1 # AddSequencerL2Batch

We will edit the addSequencerL2Batch functions in the sequencer inbox to accept a signature over the hashed calldata and the current hotshot height.

- It will first extract the hotshot height from the signature which will be the first 32 bytes - Futher it will call the EspressoTEEVerifier contract’s verify function which is outlined in Espresso TEE verifier - If the verification is successful, it will emit the last hotshot height

1    function addSequencerL2Batch( 
2        uint256 sequenceNumber, 
3        bytes calldata data, 
4        uint256 afterDelayedMessagesRead, 
5        IGasRefunder gasRefunder, 
6        uint256 prevMessageCount, 
7        uint256 newMessageCount, 
8        bytes memory batcherSignatureAndHotshotHeight 
9    ) { 
10 
11        // Filter out the first few bytes of batcherSignatureAndHotshotHeight 
12        to get the hotshot height 
13        uint256 hotshotHeight = uint256(batcherSignatureAndHotshotHeight[0:32]); 
14 
15        bytes32 digest = keccak(sequenceNumber + data + afterDelayedMessagesRead + gasRefunder + prevMessageCount + newMessageCount + hotshotHeight) 
16 
17        ( address signer) = ECDSA.tryRecover(digest, batcherSignatureAndHotshotHeight[32:]) 
18 
19        If !isBatchPoster[signer] { 
20            revert NotBatchPoster(signer); 
21        } 
22 
23        // Emit the last hotshot height 
24        // This will be used by the batch poster to determine 
25        // which hotshot height it should start 
26        // building its batch from 
27        emit LastHotshotHeight(hotshotHeight); 
28 
29         
30 
31        Handle the batch as Nitro normally would 
32 
33         
34        if batch delivered{ 
35            setLastHotshotBlock(hotshotHeight) 
36        } 
37    }

29.1.2 # AddSequencerL2BatchFromBlobs

We will edit the addSequencerL2BatchFromBlobs functions in the sequencer inbox to accept a signature over the blob hashes + metadata in a batch along with the current hotshot height. We will check that the signature is from an address contained in isBatchPoster mapping. If it is an attested signer, the contract will proceed as it would in vanilla nitro add the batch to the rollup. If it is not an attested signer, we will discard the batch.

To verify the signature we will use the OpenZeppelin ECDSA library

1    function addSequencerL2BatchFromBlobs( 
2        uint256 sequenceNumber, 
3        uint256 afterDelayedMessagesRead, 
4        IGasRefunder gasRefunder, 
5        uint256 prevMessageCount, 
6        uint256 newMessageCount, 
7        bytes memory batcherSignatureAndHotshotHeight 
8    ) { 
9 
10        // Filter out the first few bytes of batcherSignatureAndHotshotHeight 
11        to get the hotshot height 
12        uint256 hotshotHeight = uint256(batcherSignatureAndHotshotHeight[0:32]); 
13        bytes32[] memory dataHashes = reader4844.getDataHashes(); 
14 
15        bytes32 digest = keccak(sequenceNumber + dataHashes + afterDelayedMessagesRead + gasRefunder + prevMessageCount + newMessageCount + hotshotHeight) 
16 
17        // Call the EspressoTEEVerifier contract to verify the attestation quote 
18        EspressoTEEVerifier(TEE_VERIFIER).verify(batcherSignatureAndHotshotHeight[32:], digest ); 
19 
20        // Emit the last hotshot height 
21        // This will be used by the batch poster to determine 
22        // which hotshot height it should start 
23        // building its batch from 
24        emit LastHotshotHeight(hotshotHeight); 
25 
26         
27 
28        Handle the batch as Nitro normally would 
29 
30         
31        if batch delivered{ 
32            setLastHotshotBlock(hotshotHeight) 
33        } 
34    }