Consensus Modularity and Erigon-CL state of the art.

Consensus Modularity and Erigon-CL state of the art.

Very good dev doing veryyy good things :)


Hello Everyone. This is the first post of my technical blog and I am basically going to discuss what I am working on right now: Internal Consensus Modularity and Erigon-CL. So, for whoever does not know, Erigon has a special property: Each internal component can be run standalone as their own process. In its current state, the components that can be ran separantly are: Sentry (ETH 1 P2P Layer), RpcDaemon, the database itself (MDBX), Erigon-Core (The actual node), The internal CL Lightclient and Sentinel (ETH2 P2P layer). However, We also want to separate yet another component and turn it into a GRPC Microservice: Consensus. Unlike Consensus Layers however, this separation will use our own custom interface and will support different types of consensuses such as Bor, ETH2 PoS, BSC and Gnosis, so do not get confused by the terminology. Now let us go a little bit into detail in Erigon-CL and Consensus Modularity 👇👇👇

Erigon-CL (State Of the Art)

As some of the people that follows me on Twitter knows, I am currently working on an embedded Consensus Layer Implementation for Erigon. It basically will follow the ETH 2 specs and will eventually replace the Engine API. The things accomplished so far are: Prototype of an ETH 2 block downloader, a skeleton of what is going to be the beacon chain State Transition and fully working Checkpoint Sync. Currently, What I am specifically working on is the ETH 2 Block Downloader which is now working, except is quite trash because our P2P is also quite trash but it will get good. For example, It sometimes gets stuck, lose connection a lot, connects to peers from other networks, etc… I already found out a possible reason which is that we do not perform the Status Request handshake, which I am working at implementing in the following weeks. Erigon-CL also have a fully fledged and working sync cycle system so it wont just stop once it is done with a first sync but It actually listen to gossip and keep downloading new blocks once it reaches chain tip. Currently it takes 2 minutes to sync from a given Checkpoint to the chain tip, but that will be improved hopefully. Another thing: I am trying to get my implementation to take as little code as possible as I do not want it to end up with a codebase like Prysm or Lighthouse that are gigantic masses of code. I want it as simple as possible. It will probably come at a cost, for example, lack of backward compatibility with some hard forks or maybe not providing the possibility of having full CL archive node but I think that given low demand for any of the things I mentioned, it wont be a too significant issue :). In any case, future is bright I hope I will make it.

Consensus Separation (Erigon 3)

Consensus Separation is basically the separation of Consensus to a different micro-service, it is very similar to the CL →EL architecture but improved and with the possibility of supporting different Consensus algorithms other than ETH2. The communication protocol will be GRPC and this is how I designed it so far (with the help of Michelangelo, a Silkworm developer):

# Interface exposed by Execution Module to Consensus Module

InsertHeaders([]Header) →None
InsertBodies([][]Transaction) →None
ValidateChain(Hash) → ValidationOutcome
UpdateForkChoice(Hash) → ForkChoiceOutcome
AssembleBlock() → ExecutionPayload. 
GetHeader(HashOrNumber) →Header
GetBody(HashOrNumber) →[]Transaction
IsCanonicalHash(Hash) → Bool
GetHeaderHashNumber(Hash) → Block Number

Sorry if it is not highlighted, but Substack does not allow code highlighting. In any case it is just a specialized version of the Engine API for Erigon that uses GRPC instead of Json-Rpc. Note: The Consesus Module will never have ETH1 Data nor will do any execution without querying the Execution Module and Vice versa.

Another Thing that the Consensus Module does is downloading blocks and handling networking. The execution module should never touch networking. Thus making the Consensus Module the active component of the node while making the Execution Module the passive component. This separation is planned for Erigon 3 (Next big Erigon update).

Full code for the GRPC inteface

Eth2 P2P Handshaker

As I mentioned before, I have not implemented the handshake specification for Erigon ETH 2 P2P Service, which is what I am going to do next week. However, I would like to abstract as much as possible from it due to the fact that different nodes types may need different kind of peers. After we connect to another peer and receive their “Status”, aka. their “fork configuration and sync progress” we may need different checks. For example: a Full Client ETH2 client may want to connect to peers who are behind chain tip to help them get to the chain tip. However, an ETH2 light client node does not give a shit and will only connect to nodes who are fully synced to chain tip. this is because light clients work only if they are connected to fully synced nodes. At least this how I designed it so far, another thought is that I can add an extra rule for Full clients so that they reject peers too far behind in regards of weak subjectivity and if I will decide to add an Archive node option, then I will make Archive nodes connect to nodes who are that behind to help them out in their syncing adventure.


All in all, I think things are looking bright and considering the maturity of what I accomplished so far, I think Erigon-CL and the Consensus Separation actually do look good. Yes, I am still trying to add more functionality here and there and things are not super mature yet but it is good enough for the time I have been working on it
: 1 Month focusing on the ETH2 Full client + 1.5 month finishing the initial ETH2 Lightclient. There are also a bunch of other thoughts I had about compressing data and such but I will talk about it probably in the future. Also, big thanks to Mike (@m_neuder on twitter) which is helping me with state transition!

original post: