Introducing Itachi: A Fully Decentralized Modular Sequencer for Appchain, Starting from Starknet
"Itachi" introduces a revolutionary, fully decentralized sequencer framework tailored for Layer 2 (L2)/L3 Appchains, kicking off with Starknet integration. Itachi is built on the Yu framework, which was developed by the Reddio team in Golang. Golang is known for its modularity and customisation capabilities and so the Yu framework is more developer-friendly than Substrate and/or Cosmos SDK. Itachi simplifies the transaction process for users, ensuring legality and preparing transactions for consensus and execution, including checks for signature validity and preventing replay attacks.
Central to Itachi's functionality is its consensus mechanism, periodically generating L2/L3 blocks and executing them via the CairoVM to ensure seamless synchronisation with Cairo-state. This process underscores Itachi's efficiency in handling transactions, storing block data, and interfacing with Layer 1 through proof generation and Data Availability (DA) data construction.
Looking ahead, the release of Itachi's source code will empower developers to expand its capabilities, potentially integrating EVM/ZK modules for a ZK Layer 2/Layer 3 solution or BitVM/ZK modules for a BTC Layer 2 solution. Additionally, Itachi powers Reddio's own Starknet compatible zkVM Layer 2 offers high-performance capabilities, allowing for seamless deployment of Starknet smart contracts to Reddio's zkVM Layer 2 without modifications.
Now, let's dive deep into how Itachi did that.
Composition of Sequencers
Overview
The sequencer plays a crucial role in Layer 2 (L2), particularly within the ZK Rollup architecture. The core function of a sequencer is to be responsible for ordering transactions, executing them, delegating proof generation to a prover, and then sending the proof and data back to Layer 1 (L1).
The sequencer is essentially a blockchain with special functionalities. Beyond the essential components required by traditional blockchains, they also need capabilities for interfacing with ZK provers and for connecting with L1 Data Availability (DA). For ecosystems like Starknet, compatibility with Cairo contracts through a CairoVM is necessary. To implement additional distinctive features, such as customized consensus or transaction packaging methods, more modules are required. Often, these functional modules cannot be accomplished solely through smart contracts.
Due to the high cost of developing a new blockchain from scratch, many Rollup sequencers opt to fork the source code of go-ethereum and make various degrees of modifications or encapsulations to reuse the underlying components of go-ethereum as much as possible. However, for Madara and Itachi, we utilize a blockchain framework to complete this task. The advantage is that it allows for decoupling between some of the blockchain's underlying components and the core functionalities that need to be added to the sequencer. This way, should there be a need to modify or add functionalities, development iterations can be carried out at a lower cost.
Unlike Madara which uses Substrate, Itachi uses the Yu blockchain framework , a highly customizable Layer 2 Native modular blockchain framework that was developed in Golang by the Reddio team. This framework offers developers a Web API-like development experience, making it easier for developers to get started in blockchain development.
Let's take a look at the operational mechanics and processes of a sequencer compatible with Cairo contracts from a blockchain perspective:
For User
- Users submit transactions to the sequencer/Itachi via RPC. Transactions can also be received through broadcasts from other nodes in the P2P network.
- After receiving a transaction through RPC, the sequencer first conducts a legality check and preprocessing on the transaction, such as:
- Checking if the signature is valid
- Verifying whether the transaction data size is too large
- Ensuring there are no duplicate transactions (to prevent replay attacks)
3. Once the transaction data passes these checks, it is placed into the txpool (transaction pool) and simultaneously broadcast to other nodes in the public network via the P2P network.
Consensus
- Through the consensus system, the sequencer periodically generates L2 blocks. It batches a certain number of transactions from the txpool into a block and broadcasts this block to other nodes via the P2P network.
- Next, the block with packaged transactions is handed over to the CairoVM. The CairoVM executes the transactions in the block in sequence and synchronizes their execution state to the Cairo-state.
- After execution by the CairoVM, the returned data such as actualFees and traces, and partial data like the state-root are first constructed and filled into the block. Once the complete block is constructed, it is added to the end of the blockchain for storage.
For Layer 1
- Based on the executed block and the state difference (stateDiff), Data Availability (DA) data is constructed and sent to the DA layer.
- Whenever a new block is executed, it is sent to an external prover. The prover generates a zk-proof and uploads it to Ethereum Layer 1 (ETH L1) for verification.
How We Build the Sequencer
Now, let's take a look at the process and components of building a sequencer with the Yu framework.
- When a transaction is initiated from the client to the blockchain, it first undergoes a check by the txpool. Only after passing this check is it entered into the transaction pool and then broadcast to other blockchain nodes. Transactions broadcast from other nodes received via the P2P network are checked and, if approved, placed into the txpool (without being broadcast further).
- The process of land running begins with the generation of blocks, which involves a series of procedures: mining and creating blocks, broadcasting, validating blocks from other nodes, executing transactions within the blocks, and storing the blocks in the chain, among others. There is a great deal of flexibility in this process; you can implement any consensus protocol you prefer, set block times, decide how transactions are packaged, and choose when transactions are executed, etc. Interactions with the blockchain, txdb and state also occur during this process.
After each block goes through the logic of all custom tripod within the land, it enters the next block phase, where the next block is generated and processed, thus continuing in a cycle.
Next, let's take a look at the component composition of Yu:
Core Components
The following are interfaces: blockchain, txdb, and txpool, all with built-in default implementations. Developers can reimplement these interfaces if they have special requirements.
- blockchain: This is the chain structure responsible for storing block data as well as organizing the chain's structure and fork logic.
- txdb: Yu's database, which stores all the specific transaction data from blocks, receipt from transactions after execution, etc.
- txpool: The transaction pool, responsible for verifying and caching transactions received from external sources.
- state: Stores the state, holding the state after each transaction is executed.
- tripod: The fundamental minimum unit for running the blockchain and allowing developers to customize logic. Developers can customize multiple tripods, arrange them in sequence, and load them into the land for the framework to call. This is the core of the entire framework.
Within the tripod, the two most crucial functions are writing and reading:
- writing is designed for developers to customize and implement freely. It will be subjected to consensus and execution by all nodes in the network. For instance, in Starknet, the four types of transactions - declare, deployAccount, invoke, L1Handle - require customized writing for implementation.
- reading is also for developers to freely customize and implement. However, it will not undergo consensus across the network and will only be executed on the local node. For example, in Starknet, the operation of call transactions needs to be implemented through customized reading.
Underlying Components
- storage: This is the storage layer, supporting various forms of storage such as KV, SQL, and FS, all of which are interfaces. Developers can specify the required storage engine (for example, KV currently has pebble and boltdb as storage engines). Currently, the storage within the state is implemented using pebble, while the storage inside the blockchain and txdb is implemented using sqlite.
- p2p: This is the peer-to-peer network used for discovering nodes within the network and for the propagation of transactions and blocks.
- crypto(keypair): This is the component for asymmetric encryption algorithms for public and private keys, currently supporting sr25519 and ed25519. This component is in the form of an interface, allowing for the extension of other encryption algorithms.
In summary, Yu has already provided developers with some of the essential components required for a blockchain. Based on this, we only need to implement some modules that are unique to the sequencer.
For a Starknet sequencer, it is essential for the sequencer to be able to execute Cairo contracts. The execution of Cairo contracts requires the involvement of CairoVM and Cairo-state. Therefore, we need to integrate the sequencer with CairoVM and Cairo-state. To achieve this, we can use Yu to develop a tripod named "Cairo," enabling it to call CairoVM to execute contracts.
Additionally, we use the Proof of Authority (POA) tripod as the consensus mechanism for our sequencer at this stage. It's important to note that POA is a default implementation provided by Yu, so we don't need to start from scratch; we can simply reference it. However, POA is intended as a transitional measure towards a decentralized network, and we plan to develop a new L2 consensus to replace POA in the future.
Let's take a closer look at the core logic of the "Cairo" tripod, with some details omitted for brevity:
type Cairo struct {
*tripod.Tripod
cairoVM vm.VM
cairoState *CairoState
}
func NewCairo(cairoVM vm.VM, cairoState *CairoState) *Cairo {
cairo := &Cairo{
Tripod: tripod.NewTripod(),
cairoVM: cairoVM,
cairoState: cairoState,
}
cairo.SetWritings(cairo.ExecuteTxn)
return cairo
}
func (c *Cairo) ExecuteTxn(ctx *context.WriteContext) error {
tx := new(TxRequest)
ctx.BindJson(tx)
receipt , err := c.cairoVM.execute(c.cairoVM, c.cairoState, tx)
if err != nil {
return err
}
ctx.EmitExtra(receipt)
}
Next, import both the "Cairo" and "POA" tripods into Yu's startup function:
func main() {
poaTripod := poa.NewPoa()
cairoTripod := cairo.NewCairo(cairoVM, cairoState)
startup.DefaultStartup(poaTripod, cairoTripod)
}
With that, a sequencer compatible with Cairo contracts is easily completed. The overview diagram would roughly look like this:
What's Next
We are publishing the source code in two weeks time, by then, developers will be able to try it out and start to add more modules to the sequencer, things like EVM/ZK to wrap up as ZK Layer 2, BitVM/ZK for BTC Layer 2.
If Appchain is not your thing, we will be launching our zkVM Layer 2 that will be powered by our Itachi sequencer, which will allow you to deploy your Starknet smart contract smoothly to Reddio zkVM Layer 2 without any additional modification. Come back and try our high performance zkVM Layer 2 that's powered by Itachi!
Follow us on twitter to stay tuned with all the updates.