No description
Find a file
2026-02-27 15:22:40 +03:00
.github go.mod: upgrade to Go 1.25+, use 1.26 for builds 2026-02-27 11:58:56 +03:00
docs docs: update release instruction 2025-01-30 13:57:14 +03:00
formal-models formal-models: extend dBFT with additional post-commit phase 2024-06-24 14:50:14 +03:00
internal consensus: remove unused arg from fillRandom 2026-02-27 15:15:08 +03:00
timer timer: migrate TestTimer_Reset to synctest 2026-02-27 15:15:08 +03:00
.gitignore workflows: reuse org-wide linter 2024-09-10 19:22:53 +03:00
block.go *: support extra dBFT stage 2024-07-30 23:51:46 +03:00
change_view.go dbft: remove Timestamp() API from dbft.ChangeView interface 2024-03-06 17:37:24 +03:00
change_view_reason.go dbft: move payloads/block/tx/crypto interfaces to dbft package 2024-03-04 12:32:42 +03:00
change_view_reason_string.go dbft: move payloads/block/tx/crypto interfaces to dbft package 2024-03-04 12:32:42 +03:00
CHANGELOG.md go.mod: upgrade dependencies 2026-02-27 15:15:08 +03:00
check.go *: adapt state-dependent block producing time 2025-03-19 16:01:13 +03:00
commit.go *: support extra dBFT stage 2024-07-30 23:51:46 +03:00
config.go *: support dynamic block time 2025-07-16 10:28:14 +03:00
consensus_message.go *: support extra dBFT stage 2024-07-30 23:51:46 +03:00
consensus_message_type.go *: support extra dBFT stage 2024-07-30 23:51:46 +03:00
consensus_payload.go *: remove NextConsensus mentions from dBFT API 2024-03-06 17:16:14 +03:00
context.go *: rand.Read never fails with Go 1.24 2025-09-08 23:01:10 +03:00
dbft.go dbft: add leading space to comment 2025-09-24 18:59:57 +03:00
dbft_test.go *: fix QF1008 lint issue 2025-09-24 18:58:55 +03:00
go.mod go.mod: upgrade dependencies 2026-02-27 15:15:08 +03:00
go.sum go.mod: upgrade dependencies 2026-02-27 15:15:08 +03:00
helpers.go *: fix exhaustive warnings 2024-09-10 19:29:04 +03:00
helpers_test.go dbft: add caching support for precommits 2024-07-31 23:53:06 +03:00
identity.go identity: simplify PrivateKey interface 2024-11-29 16:56:22 +03:00
LICENSE.md *: add LICENSE.md file 2023-08-23 12:54:47 +03:00
pre_block.go dbft: require PreBlock for PreCommit verification 2024-09-02 16:15:01 +03:00
pre_commit.go *: support extra dBFT stage 2024-07-30 23:51:46 +03:00
prepare_request.go *: remove NextConsensus mentions from dBFT API 2024-03-06 17:16:14 +03:00
prepare_response.go dbft: replace setters with extended constructor for dbft.PrepareResponse 2024-03-05 20:58:58 +03:00
README.md dbft: improve dynamic block time documentation 2025-07-17 10:03:50 +03:00
recovery_message.go recovery: add PreCommit support 2024-07-31 23:53:06 +03:00
recovery_request.go dbft: replace setters with extended constructor for dbft.RecoveryRequest 2024-03-05 20:58:58 +03:00
rtt.go context: add simple rtt estimator 2025-01-10 15:05:50 +03:00
send.go *: fix QF1008 lint issue 2025-09-24 18:58:55 +03:00
timer.go timer: drop Sleep method 2025-02-25 18:21:45 +03:00
transaction.go dbft: move payloads/block/tx/crypto interfaces to dbft package 2024-03-04 12:32:42 +03:00

Go Reference Codecov Report GitHub release (latest SemVer) License

DBFT

This repo contains Go implementation of the dBFT 2.0 consensus algorithm and its models written in TLA⁺ language.

Design and structure

  1. All control flow is done in main dbft package. Most of the code which communicates with external world (event time events) is hidden behind interfaces, callbacks and generic parameters. As a consequence it is highly flexible and extendable. Description of config options can be found in config.go.
  2. dbft package contains PrivateKey/PublicKey interfaces which permits usage of one's own cryptography for signing blocks on Commit stage. Refer to identity.go for PrivateKey/PublicKey description. No default implementation is provided.
  3. dbft package contains Hash interface which permits usage of one's own hash implementation without additional overhead on conversions. Instantiate dBFT with custom hash implementation that matches requirements specified in the corresponding documentation. Refer to identity.go for Hash description. No default implementation is provided.
  4. dbft package contains Block and Transaction abstractions located at the block.go and transaction.go files. Every block must be able to be signed and verified as well as implement getters for main fields. Transaction is an entity which can be hashed. Two entities having equal hashes are considered equal. No default implementation is provided.
  5. dbft contains generic interfaces for payloads. No default implementation is provided.
  6. dbft contains generic Timer interface for time-related operations. timer package contains default Timer provider that can safely be used in production code. The interface itself is mostly created for tests dealing with dBFT's time-dependant behaviour.
  7. internal contains an example of custom identity types and payloads implementation used to implement an example of dBFT's usage with 6-node consensus. Refer to internal subpackages for type-specific dBFT implementation and tests. Refer to internal/simulation for an example of dBFT library usage.
  8. formal-models contains the set of dBFT's models written in TLA⁺ language and instructions on how to run and check them. Please, refer to the README for more details.

Usage

A client of the library must implement its own event loop. The library provides 6 callbacks that change the state of the consensus process:

  • Start() which initializes internal dBFT structures
  • Reset() which reinitializes the consensus process
  • OnTransaction() which must be called everytime new transaction from the list of proposed transactions appears
  • OnNewTransaction() which is an extension supplying dynamic block time functionality and must be called everytime new transaction comes to the node's memory pool if dynamic block time extension is enabled
  • OnReceive() which must be called everytime new payload is received
  • OnTimer() which must be called everytime timer fires

A minimal example can be found in internal/simulation/main.go.

Notes

  1. C# NEO node implementation works with the memory pool model, where only transaction hashes are proposed in the first step of the consensus and transactions are synchronized in the background. Some of the callbacks are in config with sole purpose to support this usecase. However it is very easy to extend PrepareRequest to also include proposed transactions.
  2. NEO has the ability to change the list nodes which verify the block (they are called Validators). This is done through GetValidators callback which is called at the start of every epoch. In the simple case where validators are constant it can return the same value everytime it is called.
  3. ProcessBlock is a callback which is called synchronously every time new block is accepted. It can or can not persist block; it also may keep the blockchain state unchanged. dBFT will NOT be initialized at the next height by itself to collect the next block until Reset is called. In other words, it's the caller's responsibility to initialize dBFT at the next height even after block collection at the current height. It's also the caller's responsibility to update the blockchain state before the next height initialization so that other callbacks including CurrentHeight and CurrentHash return new values.