NEO’s consensus mechanism, dBFT, requires consensus nodes to come to an agreement about a potential block before it can be committed to the chain. This removes the possibility of blockchain forks and provides finality (irreversibility) for transactions as soon as they show up on the blockchain, which is great for the user experience, but it can result in delays as a trade-off.

Consensus nodes on NEO take it in turns to act as speaker by proposing a block. The other nodes check the validity of the block based on a few criteria, and if the block is valid, they sign their agreement. When 66% of the total number of nodes have agreed to a block, the network state is updated with the new block added to the chain.

If a speaker does not submit a valid block (whether it fails to submit a block at all or the block is invalid) within the designated time frame (currently 15 seconds), a view change occurs. Essentially this just means a new node will propose a block, in the hopes that consensus will be achieved. Unfortunately, that means another 15-second wait, so the next block will take roughly 30 seconds. These delays caused by view changes are undesirable, but the alternative would mean the loss of finality.

At the time of writing, NEO has 7 consensus nodes. By checking block explorers such as NeoScan, we can see that every 7 blocks, the block time is roughly doubled. Due to the deterministic nature of nodes being selected as speaker, this implies that a single node is failing to propose a valid block, causing a view change. So how do we figure out which node that is?

My solution here is not particularly elegant, nor is it likely to work forever; especially in the event that transaction fees are distributed to NEO holders instead of the consensus nodes. Ideally, this information would be retrieved and analyzed in a much more direct manner. But for now, this method works.