ZK Rollup Tutorial Part 2
This section of the tutorial focuses on building a sequencer node for your Sovereign Rollup. The sequencer receives transactions from users and submits them to NomosDA, Nomos’ data availability service. This page will lead you through the steps required to implement a working sequencer node that sends messages to Nomos’ Mantle execution layer in the form of Mantle Transactions.
<aside> 💡
Make sure you have gone through the Nomos wallet tutorial[LINK] before beginning this step!
</aside>
Mantle forms the minimal execution layer of Nomos, providing a way for Sovereign Rollups to interact with Nomos. This interaction is accomplished via the use of Mantle Transactions, which consist of a sequence of Operations together with a Ledger Transaction used for paying fees and transferring funds. Mantle Transactions use cryptographic keys to verify the identity of message senders, as well as to prove that they have the funds necessary to execute the transaction.
To safeguard the correct ordering of transactions from the Sovereign Rollup, data posted is assigned to a dedicated Mantle channel. These channels form virtual “chains” on Nomos, with each message in a channel referencing its predecessor via a hash. Mantle Channels ensure that the ordering of messages in each channel does not change, allowing Sovereign Rollups to post updates to Nomos without having to wait for the blockchain to be finalised. Every Sovereign Rollup can open its own Mantle Channel and post its state updates to it, which are guaranteed to eventually be included on-chain in the correct order.
A diagram illustrating how two Mantle Channels are included in the Nomos blockchain.
Messages can only be added to a channel with the permission of a channel’s creator. The first time a message is sent to an unclaimed channel, the message signing key that signs the initial message becomes both the administrator and an accredited key. The administrator can update the list of accredited keys who are authorised to write messages to that channel.
For more information on Mantle, please read the official specification.
The sequencer node is built around a Reth node that comes with some basic functionality already built-in. This includes the ability to receive transactions via its RPC endpoints and compile them into valid Ethereum blocks. However, we still need to implement the ability to process these blocks and send them to NomosDA.
<aside> 💡
This section relies on the following files in the Nomos repository:
The first step of processing blocks is to handle transforming a Reth-made block into a correctly-encoded NomosDA blob.
Open up the sequencer-node/src/lib.rs
file, where you will add functions to encode and process blocks. Begin by adding an encode_block
function to correctly encode a block according to the scheme required by NomosDA:
sequencer-node/src/lib.rs
/// Encodes block with erasure coding, as required by NomosDA
/// Returns the encoded blob and associated metadata
pub fn encode_block(block: &Block) -> (Vec<u8>, Metadata) {
// Serialise block data into a blob of bytes
let mut blob = bincode::serialize(&block).expect("Failed to serialize block");
// INSERT ENCODING HERE
// Create a new NomosDA Metadata object with an ID and block number
let metadata = Metadata::new([0; 32], block.number.into());
// Extend the blob with zeroes to fit neatly into NomosDA chunks
let remainder = blob.len() % DaEncoderParams::MAX_BLS12_381_ENCODING_CHUNK_SIZE;
blob.extend(std::iter::repeat_n(
0,
DaEncoderParams::MAX_BLS12_381_ENCODING_CHUNK_SIZE - remainder,
));
(blob, metadata)
}
[might require some writeup about NomosDA encoding here]