First things first, what is Fantom;
Not a fan of the absolute statements, “most advanced”. The rest is straight forward, “fast, and secure consensus for distributed networks”. So this isn’t a blockchain, this is clean consensus. What you do with that consensus, is up to you. You can build a blockchain, you could also just build a distributed mesh network chat program. Up to you.
All the usual suspects, scalable, secure, fast, connected, permissionless, open-source.
The value proposition is straight forward enough, we are looking for a distributed consensus mechanism.
The concept here is asynchronous byzantine fault tolerance. The main difference here from traditional BFT, would be;
- Loosely connected assumptions between validators
- Lower message overhead via common knowledge assumptions
- Can reach consensus faster due to lower message rounds required
Next stop, the github;
86 repositories in total, definitely not going through them all. We are interested in lachesis. Main repo for lachesis is go-lachesis;
3,040 commits, 55 branches, 7 released, 32 contributors. Branch management is good but seems a little bit overused. Due for a cleanup.
The following folders are the most interesting;
- /cmd ~ this will be our entry point
- /crypto ~ usual cryptographic primatives
- /ethapi ~ eth api’s for evm ecosystem compatibility
- /evmcore ~ core evm implementation for smart contract compatibility
- /gossip ~ gossip p2p and in this case, consensus as well
- /poset ~ the directed acyclic graph used for consensus (partially ordered set)
So let’s trace through from /cmd
Mix between go-ethereum and go-lachesis imports here. From ethereum we have accounts (needed for tx compatibility), common, console, params, the node import is interesting.
From go-lachesis we have gossip and integration.
Full comments are good to see. lachesisMain is our entry point, we are looking for makeFullNode and startNode
makeConfigNode and makeAllConfigs setup the configs based on the flags or toml provided.
integration.MakeEngine creates the engine (this does all the real work), setValidator takes gossipCfg.Emitter (will trace through this)
gossip.NewService is the gossip network (useful comments)
So we need to go through integration.MakeEngine, gossip.NewService, stack.Register. Let’s get back to them, and look at startNode.
startNode, status listener and new wallet listener, looks like utils.StartNode(stack) gets everything running, so let’s look at that after we head back to integration and gossip
MakeEngine, engine := poset.New //create consensus, so let’s head over to poset;
Straight forward, creates a new Poset instance, set’s the DagConfig, the store, and the inputsource. Let’s quickly look at the Poset struct;
- dag ~ config
- Checkpoint & EpochState ~ snapshotting
- election ~ asynchronous voting
- vecClock ~ vector clock for ordering
So we will come back to election.Election, for now, let’s continue on with gossip.NewServer
Some interesting things, we see svc.engine and svc.txpool (svc is the service manager), svc.engine sets the consensus call back (applyBlock, selectValidatorGroup), svc.txtool uses evmcore txpool, svc starts up an EthAPI backend.
So what can we see so far; we can see that the node is largely running in it’s gossip layer (this is the communication core) it includes txpool, consensus callbacks and rpc API’s. Consensus is using the poset DAG which uses asynchronous voting and vector clocks for ordering.
So most of the logic we are interested in would be in gossip service and poset + election, so let’s continue tracing from utils.StartNode
utils.StartNode is in the go-ethereum repo. Now this is where looking at the code can actually be tricky, because I would head over to go-ethereum and look at utils.StartNode, and then I’ll be confused as to why the utils.StartNode didn’t look compatible with go-lachesis, this is because there is a reroute happening in the go.mod file;
So ethereum/go-ethereum is actually Fantom-foundation/go-ethereum
Normal go-ethereum, but the import wasn’t just pointing to this repo, it was also pointing to v1.9.8-ftm-03 (the branch), so we select that branch and see;
Very different picture :), that out of the way, let’s jump into the real value, poset and gossip
We don’t need to go into everything, from the research papers we know the basics, event’s are emitted by a node and include a knowledge graph of information, this information is gathered into a subgraph poset, asynchronous election occurs based on common knowledge which outpus a frame which is converted to an epoch.
Event, Epoch, etc are struct definitions with some utility functions.
Poset has a few interesting functions, checkAndSaveEvent adds an event to the graph, calculates the vector clock data and calculates the root and frame indexes.
handleElection processes the roots, and sees if a frame was decided. So, how this works is straight forward enough; I receive an event, and I tell my neighbors about that event, if they agree with that event (no conflicts) they tell their neighbors about it and they tell their neighbors about who already knows about it. So very quickly via gossip the network propagates this information. But during this process, it did something else, it shared common knowledge, the information that someone else also knows about this (with signed proof that they know). So while this information is propagating through the network it is also actually reaching consensus.
It’s this common knowledge, graph theory, and gossip properties that allow the network to not deteriorate exponentially as validators are added.
The code implementation is clean with regards to these steps. Gossip communication is included into the knowledge graph (poset), asynchronous elections are run on this information and output into frame (finalized).
Conclusion: There is a lot more to go through here, but it covers the basic touchpoints from the research papers, we have an asynchronous gossip network, that achieves consensus via gossip and common knowledge protocols, using asynchronous elections on a knowledge graph.
Personal Comment: It’s been fascinating to watch this over the last 2 years grow from concept, to research proof, to mvp, and finality