Skip to content

Commit

Permalink
dbft: move payloads/block/tx/crypto interfaces to dbft package
Browse files Browse the repository at this point in the history
Close #90.

Signed-off-by: Anna Shaleva <[email protected]>
  • Loading branch information
AnnaShaleva committed Feb 19, 2024
1 parent 4a2c44d commit 5a8dfed
Show file tree
Hide file tree
Showing 38 changed files with 628 additions and 611 deletions.
34 changes: 16 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,28 @@ 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 transactions having
equal hashes are considered equal. No default implementation is provided.
5. `dbft` contains 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)
7. `simulation` contains an example of dBFT's usage with 6-node consensus.
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.

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])
}
45 changes: 7 additions & 38 deletions block/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package block
import (
"bytes"
"encoding/gob"
"github.com/nspcc-dev/dbft"

"github.com/nspcc-dev/dbft/crypto"
"github.com/nspcc-dev/dbft/merkle"
Expand All @@ -21,43 +22,11 @@ type (
NextConsensus crypto.Uint160
}

// Block is a generic interface for a block used by dbft.
Block[H crypto.Hash, A crypto.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 crypto.PrivateKey) error
// Verify checks if signature is correct.
Verify(key crypto.PublicKey, sign []byte) error

// Transactions returns block's transaction list.
Transactions() []Transaction[H]
// SetTransactions sets block's transaction list.
SetTransactions([]Transaction[H])
}

neoBlock struct {
base

consensusData uint64
transactions []Transaction[crypto.Uint256]
transactions []dbft.Transaction[crypto.Uint256]
signature []byte
hash *crypto.Uint256
}
Expand Down Expand Up @@ -99,17 +68,17 @@ func (b *neoBlock) ConsensusData() uint64 {
}

// Transactions implements Block interface.
func (b *neoBlock) Transactions() []Transaction[crypto.Uint256] {
func (b *neoBlock) Transactions() []dbft.Transaction[crypto.Uint256] {
return b.transactions
}

// SetTransactions implements Block interface.
func (b *neoBlock) SetTransactions(txx []Transaction[crypto.Uint256]) {
func (b *neoBlock) SetTransactions(txx []dbft.Transaction[crypto.Uint256]) {
b.transactions = txx
}

// NewBlock returns new block.
func NewBlock(timestamp uint64, index uint32, nextConsensus crypto.Uint160, prevHash crypto.Uint256, version uint32, nonce uint64, txHashes []crypto.Uint256) Block[crypto.Uint256, crypto.Uint160] {
func NewBlock(timestamp uint64, index uint32, nextConsensus crypto.Uint160, prevHash crypto.Uint256, version uint32, nonce uint64, txHashes []crypto.Uint256) dbft.Block[crypto.Uint256, crypto.Uint160] {
block := new(neoBlock)
block.base.Timestamp = uint32(timestamp / 1000000000)
block.base.Index = index
Expand Down Expand Up @@ -144,7 +113,7 @@ func (b *neoBlock) GetHashData() []byte {
}

// Sign implements Block interface.
func (b *neoBlock) Sign(key crypto.PrivateKey) error {
func (b *neoBlock) Sign(key dbft.PrivateKey) error {
data := b.GetHashData()

sign, err := key.Sign(data)
Expand All @@ -158,7 +127,7 @@ func (b *neoBlock) Sign(key crypto.PrivateKey) error {
}

// Verify implements Block interface.
func (b *neoBlock) Verify(pub crypto.PublicKey, sign []byte) error {
func (b *neoBlock) Verify(pub dbft.PublicKey, sign []byte) error {
data := b.GetHashData()
return pub.Verify(data, sign)
}
Expand Down
3 changes: 2 additions & 1 deletion block/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/binary"
"encoding/gob"
"errors"
"github.com/nspcc-dev/dbft"
"testing"

"github.com/nspcc-dev/dbft/crypto"
Expand All @@ -18,7 +19,7 @@ func TestNeoBlock_Setters(t *testing.T) {

require.Equal(t, crypto.Uint256{}, b.Hash())

txs := []Transaction[crypto.Uint256]{testTx(1), testTx(2)}
txs := []dbft.Transaction[crypto.Uint256]{testTx(1), testTx(2)}
b.SetTransactions(txs)
assert.Equal(t, txs, b.Transactions())

Expand Down
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 @@ func (d *DBFT[H, A]) checkPrepare() {
count++
}

if msg.Type() == payload.PrepareRequestType {
if msg.Type() == PrepareRequestType {
hasRequest = true
}
}
Expand Down Expand Up @@ -98,7 +97,7 @@ func (d *DBFT[H, A]) checkChangeView(view byte) {
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))
}
}

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

0 comments on commit 5a8dfed

Please sign in to comment.