Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dbft: move payloads/block/tx/crypto interfaces to dbft package #97

Merged
merged 5 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ jobs:

- name: Run simulation
run: |
cd ./simulation
cd ./internal/simulation
go run main.go
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Behaviour changes:
(#94)
* rename `InitializeConsensus` dBFT method to `Reset` (#95)
* drop outdated dBFT `Service` interface (#95)
* move all default implementations to `internal` package (#97)

Improvements:
* add MIT License (#78, #79)
Expand Down
41 changes: 20 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,31 @@ This repo contains Go implementation of the dBFT 2.0 consensus algorithm and its
written in [TLA⁺](https://lamport.azurewebsites.net/tla/tla.html) language.

## Design and structure
1. All control flow is done in main package. Most of the code which communicates with external
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. `crypto` package contains `PrivateKey`/`PublicKey` interfaces which permits usage of one's own
cryptography for signing blocks on `Commit` stage.
Default implementation with ECDSA signatures is provided, BLS multisignatures could be added
in the nearest future.
3. `crypto` package contains `Hash`/`Address` interfaces which permits usage of one's own
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`/`Address` interfaces which permits usage of one's own
hash/address implementation without additional overhead on conversions. Instantiate dBFT with
custom hash/address implementation that matches requirements specified in the corresponding
documentation.
3. `block` package contains `Block` and `Transaction` abstractions.
Every block must be able to be signed and verified as well as
implement setters and getters for main fields. Minimal default implementation is provided.
`Transaction` is an entity which can be hashed. Two transactions having equal hashes are considered
equal.
4. `payload` contains interfaces for payloads and minimal implementations. Note that
default implementations do not contain any signatures, so you must wrap them or implement your
own payloads in order to sign and verify messages.
5. `timer` contains default time provider. It should make it easier to write tests
documentation. Refer to `identity.go` for `Hash`/`Address` 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 setters
and 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. `timer` contains default time provider. It should make it easier to write tests
concerning dBFT's time depending behaviour.
6. `simulation` contains an example of dBFT's usage with 6-node consensus.
7. `formal-models` contains the set of dBFT's models written in [TLA⁺](https://lamport.azurewebsites.net/tla/tla.html)
language and instructions on how to run and check them. Please, refer to the [README](./formal-models/README.md)
for more details.
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⁺](https://lamport.azurewebsites.net/tla/tla.html)
language and instructions on how to run and check them. Please, refer to the [README](./formal-models/README.md)
for more details.

## Usage
A client of the library must implement its own event loop.
Expand All @@ -44,7 +43,7 @@ process:
- `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 `simulation/main.go`.
A minimal example can be found in `internal/simulation/main.go`.

## Links
- dBFT high-level description on NEO website [https://docs.neo.org/docs/en-us/basic/consensus/dbft.html](https://docs.neo.org/docs/en-us/basic/consensus/dbft.html)
Expand Down
33 changes: 33 additions & 0 deletions block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dbft

// Block is a generic interface for a block used by dbft.
type Block[H Hash, A Address] interface {
// Hash returns block hash.
Hash() H

Version() uint32
// PrevHash returns previous block hash.
PrevHash() H
// MerkleRoot returns a merkle root of the transaction hashes.
MerkleRoot() H
// Timestamp returns block's proposal timestamp.
Timestamp() uint64
// Index returns block index.
Index() uint32
// ConsensusData is a random nonce.
ConsensusData() uint64
// NextConsensus returns hash of the validators of the next block.
NextConsensus() A

// Signature returns block's signature.
Signature() []byte
// Sign signs block and sets it's signature.
Sign(key PrivateKey) error
// Verify checks if signature is correct.
Verify(key PublicKey, sign []byte) error

// Transactions returns block's transaction list.
Transactions() []Transaction[H]
// SetTransactions sets block's transaction list.
SetTransactions([]Transaction[H])
}
22 changes: 22 additions & 0 deletions change_view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dbft

// ChangeView represents dBFT ChangeView message.
type ChangeView interface {
// NewViewNumber returns proposed view number.
NewViewNumber() byte

// SetNewViewNumber sets the proposed view number.
SetNewViewNumber(view byte)

// Timestamp returns message's timestamp.
Timestamp() uint64

// SetTimestamp sets message's timestamp.
SetTimestamp(ts uint64)

// Reason returns change view reason.
Reason() ChangeViewReason

// SetReason sets change view reason.
SetReason(reason ChangeViewReason)
}
2 changes: 1 addition & 1 deletion payload/changeview_reason.go → change_view_reason.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package payload
package dbft

//go:generate stringer -type=ChangeViewReason -linecomment

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions check.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dbft

import (
"github.com/nspcc-dev/dbft/payload"
"go.uber.org/zap"
)

Expand All @@ -20,7 +19,7 @@
count++
}

if msg.Type() == payload.PrepareRequestType {
if msg.Type() == PrepareRequestType {
hasRequest = true
}
}
Expand Down Expand Up @@ -98,7 +97,7 @@
if !d.Context.WatchOnly() {
msg := d.ChangeViewPayloads[d.MyIndex]
if msg != nil && msg.GetChangeView().NewViewNumber() < view {
d.broadcast(d.makeChangeView(uint64(d.Timer.Now().UnixNano()), payload.CVChangeAgreement))
d.broadcast(d.makeChangeView(uint64(d.Timer.Now().UnixNano()), CVChangeAgreement))

Check warning on line 100 in check.go

View check run for this annotation

Codecov / codecov/patch

check.go#L100

Added line #L100 was not covered by tests
}
}

Expand Down
11 changes: 11 additions & 0 deletions commit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dbft

// Commit is an interface for dBFT Commit message.
type Commit interface {
// Signature returns commit's signature field
// which is a block signature for the current epoch.
Signature() []byte

// SetSignature sets commit's signature.
SetSignature(signature []byte)
}
Loading
Loading