In-Depth Technical & Code Review of ‘Binance Chain’ [Pt. 1]
Over the past few days and weeks, there has been a significant amount of hype regarding ‘Binance Chain’.
But there have been few individuals that have actually taken the time to look under the hood of Binance Chain.
That’s exactly what this piece is designed to do. So, without further exposition, we’ll go ahead and dive right into it. [Originally written on April 24th, 2019]
Starting with the Documentation on Binance’s Website
To begin, there isn’t a lot of concrete information about how Binance’s chain will be structured on their front facing website. There isn't a specific white paper for the chain. However, that does not preclude our ability to still gain major insight into how the chain will work.
However, the company has decided to provide a slight hint, which can be found here at this link hosted on their website: https://docs.binance.org/acknowledgement.html
Specifically, on that page, they state:
“Our current implementation is built on forks of Tendermint and Cosmos SDK. We make use of a revised edition of Tendermint consensus and leverage its p2p networking logic, and Cosmos SDK features such as its ‘bank’ is used for basic token transactions. Part of changes have been contributed back to the project as well.
Projects like Binance Chain and Binance DEX are often built as forks of Bitcoin or as smart contracts on platforms like Ethereum. With a foundation of clean, well-structured code from Cosmos SDK, we were able to build on a codebase that we saw as a better alternative. Many thanks to the Cosmos developers and its community for their work (and for being really helpful in our issues and pull requests!)”
In an attempt to obtain greater information about how Binance Chain plans to implement their chain, we consulted the GitHub link (provided on the website).
Here is the link to their GitHub: https://github.com/binance-chain
So before we hop into evaluating Tendermint and Cosmos SDK, let’s go ahead and check Binance’s GitHub first.
Binance Chain GitHub
Below are some screenshots from the Binance Chain GitHub:
Compared to most GitHub repos for actual blockchains in the cryptocurrency space, what we can see with Binance currently is rather sparse/
For comparison, take a look at a few other projects’ GitHub repository links:
- Decred = https://github.com/decred
- Litecoin = https://github.com/litecoin-project/litecoin
- Monero = https://github.com/monero-project/monero
It goes without saying that these projects have been around in existence for significantly longer, so they will be more shelled out than Binance Chain.
However, you’ll notice that the repos themselves contain significantly facets of customization for implementation on the chain.
Evaluating the Languages (SDKs)
Binance Chain’s repo features:
SDKs (Software Development Kits), are designed to allow programmers that prefer a certain programming language (i.e., the ones that we listed above) to still code on the chain.
What Has Been Completed Thus Far
So far, it appears that Binance has successfully created binaries for their full nodes. However, it appears these full nodes are only designed to be run on the testnet and not on the ‘mainnet’ yet (which was reportedly launched ahead of schedule on April 23rd, 2019).
However, this is the most important part of what we’re going to look into because the code in the subfolders of the node implementation will give us significantly more information about how Binance is planning on structuring their chain.
Reviewing the Binance Chain Config File
The ‘config’ subfolder is the mother of all information for 99% of blockchain projects on GitHub. This is where we find information about consensus mechanisms, block creations, etc.
So, without further ado, let’s journey a bit deeper.
Specifically though, before we get to that config folder, we’re going to start at node-binary/fullnode/testnet/0.5.8 (only testnet version available; there is no mainnet version for the record).
The ‘README.md’ is posted in full above for the edification of the reader.
Here is a link to the documentation cited in the picture above: https://docs.binance.org/fullnode.html
Link to ‘state sync’ = https://docs.binance.org/fullnode.html#state-sync
The ‘state sync’ link just provides information on how the nodes will sync once connected to the testnet. Essentially, the documentation states that the nodes will automatically sync at a certain block in order to expedite the process, but more than 16 GB of memory (on whatever device is being use) should be free so that it can be allocated to this process (nothing abnormal about this).
With that out the way, let’s go ahead and check out the ‘config’ here for Binance Chain (node-binary/fullnode/testnet/0.5.8/config)
Once there, this is what can be seen (at the time of writing):
Specifically, we’re going to take a look at the first file — ‘app.toml’
Under the Hood of ‘app.toml’
To begin with, ‘toml’ is a file extension and, in this context, it is used to configure the ‘Golang’ programming language.
Let’s take a look at code here in this file:
The first thing that we can see here is the non-code statement, “Interval blocks of breathe block, if breatheBlockInterval is 0, breathe block will be created every day.”
Which gives us our first indicator as to what we’re looking at here.
Breaking Down Tendermint Core (BFT Consensus)
In order to understand the code that is written above, we must dig into the Tendermint consensus protocol.
If you’ve been reading closely, you will have noticed that this was mentioned on Binance’s website directly on the front page of their documentations.
To recap briefly, the page said:
So, now that we know how Tendermint has been implemented, let’s go ahead and (briefly) breakdown how Tendermint is supposed to work.
In order to do so, we’re going to go ahead and visit Tendermint’s GitHub page, which can be found here: https://github.com/tendermint/tendermint
Basic information about how Tendermint works can be found here: https://github.com/tendermint/tendermint/tree/master/docs/spec
Basic Summary of Tendermint
If you are familiar with PoS consensus algorithms like the one that the project $NEO uses (dBFT), then you’ll probably find that the Tendermint consensus protocol is not too difficult to grasp.
Here are some of the basic features of the protocol:
- It produces blocks (just like popular blockchains like Bitcoin, Litecoin, etc.)
- The blocks that Tendermint produces are counted chronologically and referred to by ‘block height’ (again, similar to Bitcoin — so this should fall right in line with the average cryptocurrency enthusiast’s understanding of blockchain)
- Instead of miners, there are ‘validators’ for the protocol. Specifically, it is these ‘validators’ that are responsible for deciding which blocks get in and which ones don’t. This is different than regular blockchain mining (PoW) because the decision of who gets to submit the next block on the network is not determined by who wins the ‘competition’ of mining first.
- Each ‘validator’, in specific, receives a ‘weight’.
- Tendermint Consensus has a 33% fault tolerance. In other words, up to 33% of the validators on the network can deem that a block is invalid and the block will be allowed on the network. However, if more than 33% of the validators on the network do not agree, then the block will not be published. In theory (and this has happened before), the blockchain will cease to continue producing blocks if an agreement within the fault tolerance allowance cannot be reached.
- “ Also note that information like the transaction results and the validator set are never directly included in the block — only their cryptographic digests (Merkle roots) are. Hence, verification of a block requires a separate data structure to store this information. We call this the State. Block verification also requires access to the previous block.”
What is posted above just represents the footnotes though. To delve a bit deeper, we’re going to look a bit deeper at a full guide for Tendermint that is provided for us here: https://tendermint.com/docs/introduction/what-is-tendermint.html#tendermint-vs-x
The underpinning of Tendermint’s design, as stated numerous times on the GitHub and other associated documents/files, is to facilitate consistent replication.
In specific, the documentation for Tendermint states that one of the consensus mechanism’s goals is to ensure that, “Every non-faulty machine sees the transaction log and computes the same state.”
There are also two different constituent elements in Tendermint, which are:
- Blockchain consensus engine
- Generic Application Interface (ABCI; Application Blockchain Interface)
Key Difference Between Tendermint and Proof of Work
The consensus engine’s purpose is to ensure the replication of transaction (the blockchain’s history) across all ‘validators’/nodes/machines on the network. The reason why this is different from Bitcoin’s consensus mechanism (PoW) is because PoW works under an asynchronous model. Thus, the entire network does not need to be in agreement — agreement is instead dictated by hash power (whichever blockchain version possesses the most).
This is why Bitcoin and other PoW consensus algorithms are able to experience ‘orphan/stale’ blocks.
An ‘orphan’ block can occur when two different miners (or mining entities) find a satisfactory nonce value at around the same time. When this does occur, there is a chance that two different versions of the blockchain will be in existence.
This is because each node can only relay information (establish an outbound connection) with a maximum of 8 peers.
This is hard coded into Bitcoin’s protocol (and it protects the protocol because you don’t want one party broadcasting a certain version of the blockchain to all nodes; that would centralize the protocol):
Thus, Bitcoin’s block propagation method works via exponential distribution in a curve akin to what you see below:
According to the research paper ‘Information Propagation in the Bitcoin Network’ (Decker & Wattenhofer, 2013):
“The median time until a node receives a block is 6.5 seconds whereas the mean is at 12.6 seconds. The long tail of the distribution means that even after 40 seconds there still are 5% of nodes that have not yet received the block.”
The primary reason for time delay (especially for bigger blocks) is due to latency. On a raw, literal level — it takes time for a message (i.e., block state) to be transmitted from one node to another (up to 8 others).
Thus, in the case of an ‘orphan’ block, this delay in the time it takes for nodes to receive a block from a certain party leads to a certain portion of the network accepting a different version of the blockchain than others. This is due to the basic rule of thumb for PoW, which is that the block with the most Proof of Work will be accepted.
In the case of an ‘orphan’ block, both versions will possess an equal Proof of Work. So, nodes will accept these blocks on a first-come-first-serve basis.
However, the chances of multiple orphan blocks happening are rare, if not nearly impossible at this point. Therefore, the version of the protocol that finds the next block the quickest will be accepted as the ‘real version’ and the other block will simply be invalidated.
Below is a graphic illustrating this process:
Everything that was described above about Proof of Work is possible because it is an asynchronous consensus mechanism.
Remember what we stated in the beginning of this passage?:
“The consensus engine’s [Tendermint] purpose is to ensure the replication of transaction (the blockchain’s history) across all ‘validators’/nodes/machines on the network.”
In order to do so, Tendermint must provide a synchronous consensus framework. There is simply no other way to meet the goal of replication without synchronization of some sort.
Difference Between ‘Synchronous’ and ‘Asynchronous’ Protocols
If you’re wondering what the difference is between ‘synchronous’ and ‘asynchronous’ in computing, one answer given on StackExchange’s site sums it up perfectly.
As an answer to the question of ‘What’s the difference between synchronous and asynchronous?’, one of the users stated:
“When you execute something synchronously, you wait for it to finish before moving on to another task. When you execute something asynchronously, you can move on to another task before it finishes.”
What the respondent wrote is a perfect way to describe the difference between these two terms.
More specifically, it helps us understand why there can be orphan blocks for Bitcoin and provides more validity to the statement that Proof of Work is asynchronous.
Synchronous vs. Asynchronous in Blockchain
As noted above, Bitcoin is a perfect example of an asynchronous system.
The reason why is because transactions on Bitcoin are never in a state of ‘settlement finality’ (if we exclude the implementation of ‘checkpoints’).
Conversely, consensus mechanisms like Tendermint are synchronous.
Below, is a figure from a research paper titled, ‘The Quest for Scalable Blockchain Fabric: Proof-of-Work vs. BFT’:
As we can see in the chart above, ‘synchrony’ is needed for ‘liveness’ on BFT consensus-based chains (i.e., ones that utilize PoS).
This is enumerated further in the research piece when it states:
“The BFT approach to consensus typically requires every node to know the entire set of its peer nodes participating in consensus. This in turn calls for a (logically) centralized identity management in which a trusted parties issues identities and cryptographic certificates to nodes.”
This statement and everything else written above with regards to liveness, synchronous v. asynchronous, and settlement finality is why any PoS algorithm is centralized.
Let’s take a brief look at ‘consensus finality’ now. The research piece defines it as a, “Property that mandates that a valid block, appended to the blockchain at some point in time, be never removed from the blockchain.”
Bitcoin, obviously, does not possess this property because, no matter how improbable, all transactions can technically be reversed at some point if one were to create another chain with more Proof of Work than the longest accepted chain.
This is not the case with chains that operate via a BFT consensus mechanism, such as Tendermint. This is corroborated by the research report, which explicitly states, “Consensus finality is not satisfied by PoW-based blockchains.”
Again, this brings us back to our original example of ‘orphan blocks’ on Bitcoin (and other PoW-based protocols):
Tendermint Core Transaction Validation
One aspect of Tendermint that we have not yet investigated (cracked into) is its transaction validation process.
Below is an excerpt from the Tendermint documentation that sheds a bit more light on how this process is handled:
Specifically, this is a task delegated to the application part of the protocol, which is located in the Binance Chain GitHub under the following path: node-binary/fullnode/testnet/0.5.8/config/app.toml
In order to make this work, the ABCI interfaces with the Core in order to relay information from the Core to the Application layer.
The ABCI communicates this information via 3 different information types, which are:
Below is a (figure) provided by the Tendermint team to illustrate this workflow:
Below this, is yet another figure that Tendermint uses to illustrate an ‘overview’ of its entire consensus process:
This has not been mentioned yet, but similar to NEO’s consensus protocol, the validators only have so long to determine whether a block is valid or invalid (in order to keep block times specific because there is no ‘targeting’).
This feature of Tendermint’s block creation is highlighted below:
How is the Voting Process Structured in Tendermint?
One thing that we have yet to cover up to this point in this research review is the creation of blocks for Binance Chain (which uses Tendermint Consensus).
As alluded to earlier, Tendermint consensus requires voting by ‘validators’.
Specifically, according to Tendermint documentation:
“[Validators] take turns proposing blocks of transactions and voting on them. Blocks are committed in a chain, with one block at each height.”
If, for some reason, the block that was proposed by a specific validator is not approved by 2/3 of the validators, then that validator loses their ‘turn’ and another ‘round’ commences with another validator submitting a block to be voted on.
According to the Tendermint docs, there are two different phases of voting that occur before a block is officially added to the blockchain, and they are:
The following (from the Tendermint docs) describes the ‘vote’ process adequately:
The ‘Stake’ Aspect of ‘Proof of Stake’
Tendermint introduces Proof of Stake in its most classic iteration for this portion of the protocol by implementing what Vitalik famously dubbed as the ‘Slasher’ punishment.
Below is an excerpt:
Specifically, this is how Tendermint implements the ‘Slasher’ mechanism:
Evaluating Additional Facets of Tendermint (Binance Chain)
In this section of the review, we’re going to go ahead and look at some of the additional facets of Tendermint that we have not yet gotten to cover.
Stay tuned for Part 2 of this Technical Binance Review