What You Need To Know About pBFT Consensus

For many, blockchain is a fairly new technology whose applications have yet to be explored. Despite this, it is difficult to find an area in which blockchain and a distributed ledger could not be applied. For example, IoT networks of smart devices can make it possible to create cost-efficient, fully networked, and secure smart cities using the blockchain.

Distributed ledger technologies solve a plethora of problems, including increased privacy, enhanced trust in the network, increased speed, and reduced cost of transactions.

The main features of this model are full non-repudiation and the ability to implement business logic using smart contracts with maximum accuracy, reliability, and efficiency.

In order to ensure non-repudiation and eliminate errors in the performance of smart contracts, Opporty has implemented its network consensus algorithm. The protocol has achieved 300,000 transactions per second without the full version of the consensus algorithm. The DPOS (delegated proof of stake) algorithm and the PBFT (practical byzantine fault tolerance) algorithm were used to make the consensus algorithm as secure as possible.

All decentralized, distributed systems that existed before the invention of consensus were ineffective and essentially useless.

In this network, consensus can act as a third party in disputes or conflict resolution, which is very useful for developing smart contracts.

Consensus can be reached in various ways.

The three main blockchain consensus algorithms, in order of descending popularity, are Proof of Work (PoW), Proof of Stake (PoS), and Delegated Proof of Stake (DPoS). Proof of Work is the oldest, most proven, and most frequently used consensus algorithm in the blockchain.

Proof of Work became popular thanks to Bitcoin. It was initially possible to mine Bitcoin on ordinary computers, but, due to the increasing complexity of the mining processes, this is now impossible. Therefore, miners wishing to participate in Proof of Work should build mining installations that constantly seek the next Bitcoin blockchain block.

This algorithm has long proven to be highly reliable and has played an important role. At the same time, it has a significant drawback — it requires a huge amount of electricity and special mining rigs. Therefore, the profit from currency acquisition does not compensate for losses.

Theoretically, a program that finds hashes and performs Proof of Work even faster could be invented. It would then be possible to crack the consensus, and the network would become much more decentralized.

The second algorithm, Proof of Stake, necessitates that interested parties should “vote” for the next blocks to reach consensus. Users get more coins as a reward for participating in the network in a way similar to how PoW miners get rewards for their efforts.

The Proof of Stake algorithm is still decentralized like PoW, but it does not require huge amounts of electricity and mining rigs.

A problem with PoS is that more and more tokens are accumulated by the largest token holders, elevating the risk of centralization. What is needed is an algorithm that selects consensus participants fairly and equitably, but such an algorithm would be very complex.

After Proof of Work and Proof of Stake were implemented in various cryptocurrencies, Delegated Proof of Stake (DPoS) was presented. With traditional PoS, anyone can act as a stake node. However, DPoS has elected delegates. In any context, delegates are chosen by their colleagues to perform a particular role. In a DPoS environment, only elected nodes are allowed to choose blocks and contribute to consensus.

The main advantage of DPoS is that this algorithm encourages users to behave honestly, simply because it benefits them.

Another great advantage is that DPoS provides increased scalability. If the set of node delegates is known, many parameters can be optimized, and the consensus can be achieved quickly.

Increased centralization is a downside.

DPoS is a perfect solution for Plasma Cash implementation. A child chain is needed to increase throughput. Full decentralization is not necessary for a child chain. Ideally, Plasma Cash can work as one massive operator, but a larger number of delegates increases the reliability of the network at times. They can be controlled by various mechanisms.

The DPoS algorithm only determines who can send a block to a root chain and when they can send it. It is also necessary to know whether it can be done and to reach a consensus among all validators before the block enters a root chain.

The pBFT (practical Byzantine Fault Tolerance) algorithm is used for this.

Practical Byzantine Fault Tolerance algorithm

Practical Byzantine Fault Tolerance algorithm

The algorithm is designed to work in asynchronous systems. It is optimized to ensure high performance, impressive execution time, but with a slight increase in delay.

In fact, all nodes in the pBFT model are sequentially ordered. One of them is the main node (a leader), while others are called backup nodes. All nodes in the system interact with one another. The goal of all honest nodes is to agree on the system’s state, based on the opinion of the majority. It is important to not only prove that messages came from a specific peer-to-peer node, but also to make sure that the message was not changed during transmission.

In order for the pBFT model to work correctly, the instantaneous number of malicious nodes should not equal or exceed a third of all network nodes in a relevant vulnerability window. The more nodes the system has, the less mathematically likely it is that a third of all nodes are malicious. The algorithm effectively provides both viability and security if no more than n-1/3 nodes (n is the total number of nodes) are malicious or faulty simultaneously.

As a result, sequential consistency is achieved — 2f+1 correct responses are obtained. Therefore, all nodes are in a correct consistency — consensus.

Let’s consider all the PBFT rounds with an example of the code from the Plasma Cash repo.

A client sends a request to the main node.

async function createNewBlock() { // Collect memory pool transactions into the block // should be prioritized logger.info('Trying to submit block...'); let lastBlock = await getLastBlockNumberFromDb() let newBlockNumber = lastBlock + config.contractblockStep try { let {successfulTransactions, rejectTransactions} = await validateTxsFromPool() if (rejectTransactions.length > 0) { TxMemPool.removeRejectTransactions(rejectTransactions) } if (successfulTransactions.length === 0) { logger.info('Successful transactions is not defined for this block') return false } let block = new Block({ blockNumber: newBlockNumber, transactions: successfulTransactions, }) logger.info('Holded block has ', block.transactions.length, ' transactions') let currentValidator = await validatorsQueue.getCurrentValidator() // start submit block to PBFT validators block.signer = config.plasmaNodeAddress pbft.acceptBlock(block) if (!(currentValidator === config.plasmaNodeAddress)) { logger.info('Please wait your turn to submit') return false } else { logger.info('You address is current validator. submit block...') for (let tx of successfulTransactions) { await redis.hdel('txpool', tx.getHash()) } console.log('BLOCK SUBMITTED', block.blockNumber.toString(10)) let blockDataToSig = block.getRlp() let blockHash = ethUtil.hashPersonalMessage(blockDataToSig) let key = Buffer.from(config.plasmaNodeKey, 'hex') let sig = ethUtil.ecsign(blockHash, key) logger.info('New block created') return sig } } catch (err) { logger.error('createNewBlock error ', err) }

We see that all incoming transactions are first validated and filtered. A request is then sent to check whether the current validator is an active validator. If so, the function is requested.

// start submit block to PBFT validators block.signer = config.plasmaNodeAddress pbft.acceptBlock(block)

It sends a PBFT block to the host for review, and round one takes place. This is the PREPARE phase.
Next, we begin round two.

Once there are more than N (the number of nodes) responses, the main node sends a request to backup nodes and starts checking responses. This is the COMMIT phase:

 switch (code) { case 0x07: //PREPARE this.prepareMsgs++ logger.info('PREPARE msg GOT: ', this.prepareMsgs) let bl = new Block(msg) if (bl.isValid()) { if (this.prepareMsgs > PBFT_N) { logger.info('SEND COMMIT msg', msg) this.status = COMMIT const block = new Block(msg) if (block.isValid()) { for (let peer of rlpx.getPeers()) { const eth = peer.getProtocols()[0] eth.sendMessage(0x06, msg) } this.prepareMsgs = 0 this.status = COMMIT } } } break }

Next, we have round three.

switch (code) { // …… PREPARE case 0x06: this.commitMsgs++ logger.info('COMMIT msg GOT: ', this.commitMsgs) if (this.commitMsgs > PBFT_F) { // resetting this.prepareMsgs = 0 this.commitMsgs = 0 this.status = INIT logger.info('SUBMIT AND CALL msg:', this.callback) this.callback && this.callback() }

After a block is received, the number of commit messages is counted. If this number is higher than N*2+1 (PBFT_F), the block is validated and accepted.

In this way, it is possible to reach a consensus at the level of a specific block in Plasma. This consensus is very fast and suitable for use in a child chain. It helps to process all calculations outside the main chain.

A consensus is even more optimized in Plasma because non-standard block signing methods are applied. A non-interactive version of threshold BLS signatures is used to sign blocks. These signatures, along with the PBFT algorithm, provide advanced cryptographic security.

This UrIoTNews article is syndicated fromDzone