Requirements: Nitro Integration Requirements
Contents |
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.
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 }
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 }