Skip to content

Commit

Permalink
*: remove NextConsensus mentions from dBFT API
Browse files Browse the repository at this point in the history
NextConsensus API is not used by the users of dBFT. NextConsensus
handling (proposal, verification and agrreement) is moved to the upper
level of dBFT users. Starting from this commit NextConsensus
verification should be performed by dBFT user manually in
WithVerifyPrepareRequest callback.

A part of #84.

Signed-off-by: Anna Shaleva <[email protected]>
  • Loading branch information
AnnaShaleva committed Mar 6, 2024
1 parent 1db32ec commit 71143cd
Show file tree
Hide file tree
Showing 16 changed files with 16 additions and 77 deletions.
2 changes: 0 additions & 2 deletions block.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ type Block[H Hash, A Address] interface {
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
Expand Down
15 changes: 2 additions & 13 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,10 @@ type Config[H Hash, A Address] struct {
// list of the validators of the next block.
// If this function ever returns 0-length slice, dbft will panic.
GetValidators func(...Transaction[H]) []PublicKey
// GetConsensusAddress returns hash of the validator list.
GetConsensusAddress func(...PublicKey) A
// NewConsensusPayload is a constructor for payload.ConsensusPayload.
NewConsensusPayload func(*Context[H, A], MessageType, any) ConsensusPayload[H, A]
// NewPrepareRequest is a constructor for payload.PrepareRequest.
NewPrepareRequest func(ts uint64, nonce uint64, nextConsensus A, transactionHashes []H) PrepareRequest[H, A]
NewPrepareRequest func(ts uint64, nonce uint64, transactionHashes []H) PrepareRequest[H]
// NewPrepareResponse is a constructor for payload.PrepareResponse.
NewPrepareResponse func(preparationHash H) PrepareResponse[H]
// NewChangeView is a constructor for payload.ChangeView.
Expand Down Expand Up @@ -120,8 +118,6 @@ func checkConfig[H Hash, A Address](cfg *Config[H, A]) error {
return errors.New("GetValidators is nil")
} else if cfg.NewBlockFromContext == nil {
return errors.New("NewBlockFromContext is nil")
} else if cfg.GetConsensusAddress == nil {
return errors.New("GetConsensusAddress is nil")
} else if cfg.NewConsensusPayload == nil {
return errors.New("NewConsensusPayload is nil")
} else if cfg.NewPrepareRequest == nil {
Expand Down Expand Up @@ -291,13 +287,6 @@ func WithGetValidators[H Hash, A Address](f func(...Transaction[H]) []PublicKey)
}
}

// WithGetConsensusAddress sets GetConsensusAddress.
func WithGetConsensusAddress[H Hash, A Address](f func(keys ...PublicKey) A) func(config *Config[H, A]) {
return func(cfg *Config[H, A]) {
cfg.GetConsensusAddress = f
}
}

// WithNewConsensusPayload sets NewConsensusPayload.
func WithNewConsensusPayload[H Hash, A Address](f func(*Context[H, A], MessageType, any) ConsensusPayload[H, A]) func(config *Config[H, A]) {
return func(cfg *Config[H, A]) {
Expand All @@ -306,7 +295,7 @@ func WithNewConsensusPayload[H Hash, A Address](f func(*Context[H, A], MessageTy
}

// WithNewPrepareRequest sets NewPrepareRequest.
func WithNewPrepareRequest[H Hash, A Address](f func(ts uint64, nonce uint64, nextConsensus A, transactionsHashes []H) PrepareRequest[H, A]) func(config *Config[H, A]) {
func WithNewPrepareRequest[H Hash, A Address](f func(ts uint64, nonce uint64, transactionsHashes []H) PrepareRequest[H]) func(config *Config[H, A]) {
return func(cfg *Config[H, A]) {
cfg.NewPrepareRequest = f
}
Expand Down
2 changes: 1 addition & 1 deletion consensus_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type ConsensusMessage[H Hash, A Address] interface {
// GetChangeView returns payload as if it was ChangeView.
GetChangeView() ChangeView
// GetPrepareRequest returns payload as if it was PrepareRequest.
GetPrepareRequest() PrepareRequest[H, A]
GetPrepareRequest() PrepareRequest[H]
// GetPrepareResponse returns payload as if it was PrepareResponse.
GetPrepareResponse() PrepareResponse[H]
// GetCommit returns payload as if it was Commit.
Expand Down
5 changes: 0 additions & 5 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ type Context[H Hash, A Address] struct {
PrimaryIndex uint
Version uint32

// NextConsensus is a hash of the validators which will be accepting the next block.
NextConsensus A
// PrevHash is a hash of the previous block.
PrevHash H

Expand Down Expand Up @@ -261,9 +259,6 @@ func (c *Context[H, A]) Fill() {
c.Transactions[h] = txx[i]
}

validators := c.Config.GetValidators(txx...)
c.NextConsensus = c.Config.GetConsensusAddress(validators...)

c.Timestamp = c.lastBlockTimestamp + c.Config.TimestampIncrement
if now := c.getTimestamp(); now > c.Timestamp {
c.Timestamp = now
Expand Down
6 changes: 0 additions & 6 deletions dbft.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ func (d *DBFT[H, A]) onPrepareRequest(msg ConsensusPayload[H, A]) {

d.Timestamp = p.Timestamp()
d.Nonce = p.Nonce()
d.NextConsensus = p.NextConsensus()
d.TransactionHashes = p.TransactionHashes()

d.Logger.Info("received PrepareRequest", zap.Uint16("validator", msg.ValidatorIndex()), zap.Int("tx", len(d.TransactionHashes)))
Expand Down Expand Up @@ -374,11 +373,6 @@ func (d *DBFT[H, A]) createAndCheckBlock() bool {
for _, h := range d.TransactionHashes {
txx = append(txx, d.Transactions[h])
}
if d.NextConsensus != d.GetConsensusAddress(d.GetValidators(txx...)...) {
d.Logger.Error("invalid nextConsensus in proposed block")
d.sendChangeView(CVBlockRejectedByPolicy)
return false
}
if b := d.Context.CreateBlock(); !d.VerifyBlock(b) {
d.Logger.Warn("proposed block fails verification")
d.sendChangeView(CVTxInvalid)
Expand Down
18 changes: 3 additions & 15 deletions dbft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,13 +443,6 @@ func TestDBFT_Invalid(t *testing.T) {
opts = append(opts, dbft.WithNewBlockFromContext[crypto.Uint256, crypto.Uint160](func(_ *dbft.Context[crypto.Uint256, crypto.Uint160]) dbft.Block[crypto.Uint256, crypto.Uint160] {
return nil
}))
t.Run("without GetConsensusAddress", func(t *testing.T) {
require.Nil(t, dbft.New(opts...))
})

opts = append(opts, dbft.WithGetConsensusAddress[crypto.Uint256, crypto.Uint160](func(_ ...dbft.PublicKey) crypto.Uint160 {
return crypto.Uint160{}
}))
t.Run("without NewConsensusPayload", func(t *testing.T) {
require.Nil(t, dbft.New(opts...))
})
Expand All @@ -461,7 +454,7 @@ func TestDBFT_Invalid(t *testing.T) {
require.Nil(t, dbft.New(opts...))
})

opts = append(opts, dbft.WithNewPrepareRequest[crypto.Uint256, crypto.Uint160](func(uint64, uint64, crypto.Uint160, []crypto.Uint256) dbft.PrepareRequest[crypto.Uint256, crypto.Uint160] {
opts = append(opts, dbft.WithNewPrepareRequest[crypto.Uint256, crypto.Uint160](func(uint64, uint64, []crypto.Uint256) dbft.PrepareRequest[crypto.Uint256] {
return nil
}))
t.Run("without NewPrepareResponse", func(t *testing.T) {
Expand Down Expand Up @@ -760,7 +753,7 @@ func (s testState) getPrepareRequest(from uint16, hashes ...crypto.Uint256) Payl
}

func (s testState) getPrepareRequestWithHeight(from uint16, height uint32, hashes ...crypto.Uint256) Payload {
req := payload.NewPrepareRequest(0, 0, s.nextConsensus(), hashes)
req := payload.NewPrepareRequest(0, 0, hashes)

p := payload.NewConsensusPayload(dbft.PrepareRequestType, height, from, 0, req)
return p
Expand Down Expand Up @@ -812,10 +805,6 @@ func (s testState) copyWithIndex(myIndex int) *testState {
}
}

func (s testState) nextConsensus(...dbft.PublicKey) crypto.Uint160 {
return crypto.Uint160{1}
}

func (s *testState) getOptions() []func(*dbft.Config[crypto.Uint256, crypto.Uint160]) {
opts := []func(*dbft.Config[crypto.Uint256, crypto.Uint160]){
dbft.WithCurrentHeight[crypto.Uint256, crypto.Uint160](func() uint32 { return s.currHeight }),
Expand All @@ -825,7 +814,6 @@ func (s *testState) getOptions() []func(*dbft.Config[crypto.Uint256, crypto.Uint
dbft.WithBroadcast[crypto.Uint256, crypto.Uint160](func(p Payload) { s.ch = append(s.ch, p) }),
dbft.WithGetTx[crypto.Uint256, crypto.Uint160](s.pool.Get),
dbft.WithProcessBlock[crypto.Uint256, crypto.Uint160](func(b dbft.Block[crypto.Uint256, crypto.Uint160]) { s.blocks = append(s.blocks, b) }),
dbft.WithGetConsensusAddress[crypto.Uint256, crypto.Uint160](s.nextConsensus),
dbft.WithWatchOnly[crypto.Uint256, crypto.Uint160](func() bool { return false }),
dbft.WithGetBlock[crypto.Uint256, crypto.Uint160](func(crypto.Uint256) dbft.Block[crypto.Uint256, crypto.Uint160] { return nil }),
dbft.WithTimer[crypto.Uint256, crypto.Uint160](timer.New()),
Expand Down Expand Up @@ -867,7 +855,7 @@ func newBlockFromContext(ctx *dbft.Context[crypto.Uint256, crypto.Uint160]) dbft
if ctx.TransactionHashes == nil {
return nil
}
block := block.NewBlock(ctx.Timestamp, ctx.BlockIndex, ctx.NextConsensus, ctx.PrevHash, ctx.Version, ctx.Nonce, ctx.TransactionHashes)
block := block.NewBlock(ctx.Timestamp, ctx.BlockIndex, ctx.PrevHash, ctx.Version, ctx.Nonce, ctx.TransactionHashes)
return block
}

Expand Down
2 changes: 1 addition & 1 deletion helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (p payloadStub) SetPayload(any) {
func (p payloadStub) GetChangeView() ChangeView {
panic("TODO")
}
func (p payloadStub) GetPrepareRequest() PrepareRequest[hash, address] {
func (p payloadStub) GetPrepareRequest() PrepareRequest[hash] {
panic("TODO")
}
func (p payloadStub) GetPrepareResponse() PrepareResponse[hash] {
Expand Down
9 changes: 1 addition & 8 deletions internal/block/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ type (
Version uint32
MerkleRoot crypto.Uint256
PrevHash crypto.Uint256
NextConsensus crypto.Uint160
}

neoBlock struct {
Expand Down Expand Up @@ -52,11 +51,6 @@ func (b *neoBlock) Index() uint32 {
return b.base.Index
}

// NextConsensus implements Block interface.
func (b *neoBlock) NextConsensus() crypto.Uint160 {
return b.base.NextConsensus
}

// MerkleRoot implements Block interface.
func (b *neoBlock) MerkleRoot() crypto.Uint256 {
return b.base.MerkleRoot
Expand All @@ -78,11 +72,10 @@ func (b *neoBlock) SetTransactions(txx []dbft.Transaction[crypto.Uint256]) {
}

// NewBlock returns new block.
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] {
func NewBlock(timestamp uint64, index uint32, 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
block.base.NextConsensus = nextConsensus
block.base.PrevHash = prevHash
block.base.Version = version
block.base.ConsensusData = nonce
Expand Down
3 changes: 0 additions & 3 deletions internal/block/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ func TestNeoBlock_Setters(t *testing.T) {
b.base.Version = 42
assert.EqualValues(t, 42, b.Version())

b.base.NextConsensus = crypto.Uint160{1}
assert.Equal(t, crypto.Uint160{1}, b.NextConsensus())

b.base.PrevHash = crypto.Uint256{3, 7}
assert.Equal(t, crypto.Uint256{3, 7}, b.PrevHash())

Expand Down
4 changes: 2 additions & 2 deletions internal/payload/consensus_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ func (m *message) DecodeBinary(r *gob.Decoder) error {
}

func (m message) GetChangeView() dbft.ChangeView { return m.payload.(dbft.ChangeView) }
func (m message) GetPrepareRequest() dbft.PrepareRequest[crypto.Uint256, crypto.Uint160] {
return m.payload.(dbft.PrepareRequest[crypto.Uint256, crypto.Uint160])
func (m message) GetPrepareRequest() dbft.PrepareRequest[crypto.Uint256] {
return m.payload.(dbft.PrepareRequest[crypto.Uint256])
}
func (m message) GetPrepareResponse() dbft.PrepareResponse[crypto.Uint256] {
return m.payload.(dbft.PrepareResponse[crypto.Uint256])
Expand Down
3 changes: 1 addition & 2 deletions internal/payload/constructors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ func NewConsensusPayload(t dbft.MessageType, height uint32, validatorIndex uint1
}

// NewPrepareRequest returns minimal prepareRequest implementation.
func NewPrepareRequest(ts uint64, nonce uint64, nextConsensus crypto.Uint160, transactionsHashes []crypto.Uint256) dbft.PrepareRequest[crypto.Uint256, crypto.Uint160] {
func NewPrepareRequest(ts uint64, nonce uint64, transactionsHashes []crypto.Uint256) dbft.PrepareRequest[crypto.Uint256] {
return &prepareRequest{
transactionHashes: transactionsHashes,
nonce: nonce,
timestamp: nanoSecToSec(ts),
nextConsensus: nextConsensus,
}
}

Expand Down
11 changes: 1 addition & 10 deletions internal/payload/prepare_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,23 @@ type (
transactionHashes []crypto.Uint256
nonce uint64
timestamp uint32
nextConsensus crypto.Uint160
}
// prepareRequestAux is an auxiliary structure for prepareRequest encoding.
prepareRequestAux struct {
TransactionHashes []crypto.Uint256
Nonce uint64
Timestamp uint32
NextConsensus crypto.Uint160
}
)

var _ dbft.PrepareRequest[crypto.Uint256, crypto.Uint160] = (*prepareRequest)(nil)
var _ dbft.PrepareRequest[crypto.Uint256] = (*prepareRequest)(nil)

// EncodeBinary implements Serializable interface.
func (p prepareRequest) EncodeBinary(w *gob.Encoder) error {
return w.Encode(&prepareRequestAux{
TransactionHashes: p.transactionHashes,
Nonce: p.nonce,
Timestamp: p.timestamp,
NextConsensus: p.nextConsensus,
})
}

Expand All @@ -44,7 +41,6 @@ func (p *prepareRequest) DecodeBinary(r *gob.Decoder) error {

p.timestamp = aux.Timestamp
p.nonce = aux.Nonce
p.nextConsensus = aux.NextConsensus
p.transactionHashes = aux.TransactionHashes
return nil
}
Expand All @@ -63,8 +59,3 @@ func (p prepareRequest) Nonce() uint64 {
func (p prepareRequest) TransactionHashes() []crypto.Uint256 {
return p.transactionHashes
}

// NextConsensus implements PrepareRequest interface.
func (p prepareRequest) NextConsensus() crypto.Uint160 {
return p.nextConsensus
}
3 changes: 1 addition & 2 deletions internal/payload/recovery_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type (
preparationPayloads []preparationCompact
commitPayloads []commitCompact
changeViewPayloads []changeViewCompact
prepareRequest dbft.PrepareRequest[crypto.Uint256, crypto.Uint160]
prepareRequest dbft.PrepareRequest[crypto.Uint256]
}
// recoveryMessageAux is an auxiliary structure for recoveryMessage encoding.
recoveryMessageAux struct {
Expand Down Expand Up @@ -80,7 +80,6 @@ func (m *recoveryMessage) GetPrepareRequest(p dbft.ConsensusPayload[crypto.Uint2
timestamp: nanoSecToSec(m.prepareRequest.Timestamp()),
nonce: m.prepareRequest.Nonce(),
transactionHashes: m.prepareRequest.TransactionHashes(),
nextConsensus: m.prepareRequest.NextConsensus(),
})
req.SetValidatorIndex(ind)

Expand Down
3 changes: 1 addition & 2 deletions internal/simulation/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func newBlockFromContext(ctx *dbft.Context[crypto.Uint256, crypto.Uint160]) dbft
if ctx.TransactionHashes == nil {
return nil
}
block := block.NewBlock(ctx.Timestamp, ctx.BlockIndex, ctx.NextConsensus, ctx.PrevHash, ctx.Version, ctx.Nonce, ctx.TransactionHashes)
block := block.NewBlock(ctx.Timestamp, ctx.BlockIndex, ctx.PrevHash, ctx.Version, ctx.Nonce, ctx.TransactionHashes)
return block
}

Expand Down Expand Up @@ -151,7 +151,6 @@ func initSimNode(nodes []*simNode, i int, log *zap.Logger) error {
dbft.WithVerifyPrepareResponse[crypto.Uint256, crypto.Uint160](nodes[i].VerifyPayload),

dbft.WithNewBlockFromContext[crypto.Uint256, crypto.Uint160](newBlockFromContext),
dbft.WithGetConsensusAddress[crypto.Uint256, crypto.Uint160](func(...dbft.PublicKey) crypto.Uint160 { return crypto.Uint160{} }),
dbft.WithNewConsensusPayload[crypto.Uint256, crypto.Uint160](defaultNewConsensusPayload),
dbft.WithNewPrepareRequest[crypto.Uint256, crypto.Uint160](payload.NewPrepareRequest),
dbft.WithNewPrepareResponse[crypto.Uint256, crypto.Uint160](payload.NewPrepareResponse),
Expand Down
5 changes: 1 addition & 4 deletions prepare_request.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package dbft

// PrepareRequest represents dBFT PrepareRequest message.
type PrepareRequest[H Hash, A Address] interface {
type PrepareRequest[H Hash] interface {
// Timestamp returns this message's timestamp.
Timestamp() uint64
// Nonce is a random nonce.
Nonce() uint64
// TransactionHashes returns hashes of all transaction in a proposed block.
TransactionHashes() []H
// NextConsensus returns hash which is based on which validators will
// try to agree on a block in the current epoch.
NextConsensus() A
}
2 changes: 1 addition & 1 deletion send.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (d *DBFT[H, A]) broadcast(msg ConsensusPayload[H, A]) {
func (c *Context[H, A]) makePrepareRequest() ConsensusPayload[H, A] {
c.Fill()

req := c.Config.NewPrepareRequest(c.Timestamp, c.Nonce, c.NextConsensus, c.TransactionHashes)
req := c.Config.NewPrepareRequest(c.Timestamp, c.Nonce, c.TransactionHashes)

return c.Config.NewConsensusPayload(c, PrepareRequestType, req)
}
Expand Down

0 comments on commit 71143cd

Please sign in to comment.