From c283b803d91e0dcd1002a9c79fb601a821391a9f Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 6 Mar 2024 12:39:21 +0300 Subject: [PATCH] *: remove NextConsensus mentions from dBFT API 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 --- block.go | 4 +- check.go | 6 +- config.go | 163 ++++++++++++-------------- consensus_message.go | 6 +- consensus_payload.go | 4 +- context.go | 73 ++++++------ dbft.go | 68 +++++------ dbft_test.go | 142 ++++++++++------------ helpers.go | 34 +++--- helpers_test.go | 11 +- identity.go | 10 -- internal/block/block.go | 12 +- internal/block/block_test.go | 3 - internal/payload/consensus_message.go | 10 +- internal/payload/constructors.go | 7 +- internal/payload/message.go | 2 +- internal/payload/message_test.go | 4 +- internal/payload/prepare_request.go | 11 +- internal/payload/recovery_message.go | 23 ++-- internal/simulation/main.go | 63 +++++----- prepare_request.go | 5 +- recovery_message.go | 12 +- send.go | 26 ++-- 23 files changed, 312 insertions(+), 387 deletions(-) diff --git a/block.go b/block.go index c849fc89..af3bf6b2 100644 --- a/block.go +++ b/block.go @@ -1,7 +1,7 @@ package dbft // Block is a generic interface for a block used by dbft. -type Block[H Hash, A Address] interface { +type Block[H Hash] interface { // Hash returns block hash. Hash() H @@ -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 diff --git a/check.go b/check.go index a3a3d72d..4b4b9e15 100644 --- a/check.go +++ b/check.go @@ -4,7 +4,7 @@ import ( "go.uber.org/zap" ) -func (d *DBFT[H, A]) checkPrepare() { +func (d *DBFT[H]) checkPrepare() { if !d.hasAllTransactions() { d.Logger.Debug("check prepare: some transactions are missing", zap.Any("hashes", d.MissingTransactions)) return @@ -36,7 +36,7 @@ func (d *DBFT[H, A]) checkPrepare() { } } -func (d *DBFT[H, A]) checkCommit() { +func (d *DBFT[H]) checkCommit() { if !d.hasAllTransactions() { d.Logger.Debug("check commit: some transactions are missing", zap.Any("hashes", d.MissingTransactions)) return @@ -77,7 +77,7 @@ func (d *DBFT[H, A]) checkCommit() { // new height. } -func (d *DBFT[H, A]) checkChangeView(view byte) { +func (d *DBFT[H]) checkChangeView(view byte) { if d.ViewNumber >= view { return } diff --git a/config.go b/config.go index d0b3f316..014785e4 100644 --- a/config.go +++ b/config.go @@ -10,7 +10,7 @@ import ( ) // Config contains initialization and working parameters for dBFT. -type Config[H Hash, A Address] struct { +type Config[H Hash] struct { // Logger Logger *zap.Logger // Timer @@ -26,7 +26,7 @@ type Config[H Hash, A Address] struct { // together with it's key pair. GetKeyPair func([]PublicKey) (int, PrivateKey, PublicKey) // NewBlockFromContext should allocate, fill from Context and return new block.Block. - NewBlockFromContext func(ctx *Context[H, A]) Block[H, A] + NewBlockFromContext func(ctx *Context[H]) Block[H] // RequestTx is a callback which is called when transaction contained // in current block can't be found in memory pool. RequestTx func(h ...H) @@ -39,13 +39,13 @@ type Config[H Hash, A Address] struct { // to be proposed in a new block. GetVerified func() []Transaction[H] // VerifyBlock verifies if block is valid. - VerifyBlock func(b Block[H, A]) bool + VerifyBlock func(b Block[H]) bool // Broadcast should broadcast payload m to the consensus nodes. - Broadcast func(m ConsensusPayload[H, A]) + Broadcast func(m ConsensusPayload[H]) // ProcessBlock is called every time new block is accepted. - ProcessBlock func(b Block[H, A]) + ProcessBlock func(b Block[H]) // GetBlock should return block with hash. - GetBlock func(h H) Block[H, A] + GetBlock func(h H) Block[H] // WatchOnly tells if a node should only watch. WatchOnly func() bool // CurrentHeight returns index of the last accepted block. @@ -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] + NewConsensusPayload func(*Context[H], MessageType, any) ConsensusPayload[H] // 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. @@ -72,20 +70,20 @@ type Config[H Hash, A Address] struct { // NewRecoveryRequest is a constructor for payload.RecoveryRequest. NewRecoveryRequest func(ts uint64) RecoveryRequest // NewRecoveryMessage is a constructor for payload.RecoveryMessage. - NewRecoveryMessage func() RecoveryMessage[H, A] + NewRecoveryMessage func() RecoveryMessage[H] // VerifyPrepareRequest can perform external payload verification and returns true iff it was successful. - VerifyPrepareRequest func(p ConsensusPayload[H, A]) error + VerifyPrepareRequest func(p ConsensusPayload[H]) error // VerifyPrepareResponse performs external PrepareResponse verification and returns nil if it's successful. - VerifyPrepareResponse func(p ConsensusPayload[H, A]) error + VerifyPrepareResponse func(p ConsensusPayload[H]) error } const defaultSecondsPerBlock = time.Second * 15 const defaultTimestampIncrement = uint64(time.Millisecond / time.Nanosecond) -func defaultConfig[H Hash, A Address]() *Config[H, A] { +func defaultConfig[H Hash]() *Config[H] { // fields which are set to nil must be provided from client - return &Config[H, A]{ + return &Config[H]{ Logger: zap.NewNop(), Timer: timer.New(), SecondsPerBlock: defaultSecondsPerBlock, @@ -95,21 +93,21 @@ func defaultConfig[H Hash, A Address]() *Config[H, A] { StopTxFlow: func() {}, GetTx: func(H) Transaction[H] { return nil }, GetVerified: func() []Transaction[H] { return make([]Transaction[H], 0) }, - VerifyBlock: func(Block[H, A]) bool { return true }, - Broadcast: func(ConsensusPayload[H, A]) {}, - ProcessBlock: func(Block[H, A]) {}, - GetBlock: func(H) Block[H, A] { return nil }, + VerifyBlock: func(Block[H]) bool { return true }, + Broadcast: func(ConsensusPayload[H]) {}, + ProcessBlock: func(Block[H]) {}, + GetBlock: func(H) Block[H] { return nil }, WatchOnly: func() bool { return false }, CurrentHeight: nil, CurrentBlockHash: nil, GetValidators: nil, - VerifyPrepareRequest: func(ConsensusPayload[H, A]) error { return nil }, - VerifyPrepareResponse: func(ConsensusPayload[H, A]) error { return nil }, + VerifyPrepareRequest: func(ConsensusPayload[H]) error { return nil }, + VerifyPrepareResponse: func(ConsensusPayload[H]) error { return nil }, } } -func checkConfig[H Hash, A Address](cfg *Config[H, A]) error { +func checkConfig[H Hash](cfg *Config[H]) error { if cfg.GetKeyPair == nil { return errors.New("private key is nil") } else if cfg.CurrentHeight == nil { @@ -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 { @@ -143,13 +139,13 @@ func checkConfig[H Hash, A Address](cfg *Config[H, A]) error { // WithKeyPair sets GetKeyPair to a function returning default key pair // if it is present in a list of validators. -func WithKeyPair[H Hash, A Address](priv PrivateKey, pub PublicKey) func(config *Config[H, A]) { +func WithKeyPair[H Hash](priv PrivateKey, pub PublicKey) func(config *Config[H]) { myPub, err := pub.MarshalBinary() if err != nil { return nil } - return func(cfg *Config[H, A]) { + return func(cfg *Config[H]) { cfg.GetKeyPair = func(ps []PublicKey) (int, PrivateKey, PublicKey) { for i := range ps { pi, err := ps[i].MarshalBinary() @@ -166,197 +162,190 @@ func WithKeyPair[H Hash, A Address](priv PrivateKey, pub PublicKey) func(config } // WithGetKeyPair sets GetKeyPair. -func WithGetKeyPair[H Hash, A Address](f func([]PublicKey) (int, PrivateKey, PublicKey)) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithGetKeyPair[H Hash](f func([]PublicKey) (int, PrivateKey, PublicKey)) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.GetKeyPair = f } } // WithLogger sets Logger. -func WithLogger[H Hash, A Address](log *zap.Logger) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithLogger[H Hash](log *zap.Logger) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.Logger = log } } // WithTimer sets Timer. -func WithTimer[H Hash, A Address](t timer.Timer) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithTimer[H Hash](t timer.Timer) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.Timer = t } } // WithSecondsPerBlock sets SecondsPerBlock. -func WithSecondsPerBlock[H Hash, A Address](d time.Duration) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithSecondsPerBlock[H Hash](d time.Duration) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.SecondsPerBlock = d } } // WithTimestampIncrement sets TimestampIncrement. -func WithTimestampIncrement[H Hash, A Address](u uint64) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithTimestampIncrement[H Hash](u uint64) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.TimestampIncrement = u } } // WithNewBlockFromContext sets NewBlockFromContext. -func WithNewBlockFromContext[H Hash, A Address](f func(ctx *Context[H, A]) Block[H, A]) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithNewBlockFromContext[H Hash](f func(ctx *Context[H]) Block[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewBlockFromContext = f } } // WithRequestTx sets RequestTx. -func WithRequestTx[H Hash, A Address](f func(h ...H)) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithRequestTx[H Hash](f func(h ...H)) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.RequestTx = f } } // WithStopTxFlow sets StopTxFlow. -func WithStopTxFlow[H Hash, A Address](f func()) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithStopTxFlow[H Hash](f func()) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.StopTxFlow = f } } // WithGetTx sets GetTx. -func WithGetTx[H Hash, A Address](f func(h H) Transaction[H]) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithGetTx[H Hash](f func(h H) Transaction[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.GetTx = f } } // WithGetVerified sets GetVerified. -func WithGetVerified[H Hash, A Address](f func() []Transaction[H]) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithGetVerified[H Hash](f func() []Transaction[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.GetVerified = f } } // WithVerifyBlock sets VerifyBlock. -func WithVerifyBlock[H Hash, A Address](f func(b Block[H, A]) bool) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithVerifyBlock[H Hash](f func(b Block[H]) bool) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.VerifyBlock = f } } // WithBroadcast sets Broadcast. -func WithBroadcast[H Hash, A Address](f func(m ConsensusPayload[H, A])) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithBroadcast[H Hash](f func(m ConsensusPayload[H])) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.Broadcast = f } } // WithProcessBlock sets ProcessBlock. -func WithProcessBlock[H Hash, A Address](f func(b Block[H, A])) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithProcessBlock[H Hash](f func(b Block[H])) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.ProcessBlock = f } } // WithGetBlock sets GetBlock. -func WithGetBlock[H Hash, A Address](f func(h H) Block[H, A]) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithGetBlock[H Hash](f func(h H) Block[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.GetBlock = f } } // WithWatchOnly sets WatchOnly. -func WithWatchOnly[H Hash, A Address](f func() bool) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithWatchOnly[H Hash](f func() bool) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.WatchOnly = f } } // WithCurrentHeight sets CurrentHeight. -func WithCurrentHeight[H Hash, A Address](f func() uint32) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithCurrentHeight[H Hash](f func() uint32) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.CurrentHeight = f } } // WithCurrentBlockHash sets CurrentBlockHash. -func WithCurrentBlockHash[H Hash, A Address](f func() H) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithCurrentBlockHash[H Hash](f func() H) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.CurrentBlockHash = f } } // WithGetValidators sets GetValidators. -func WithGetValidators[H Hash, A Address](f func(...Transaction[H]) []PublicKey) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithGetValidators[H Hash](f func(...Transaction[H]) []PublicKey) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.GetValidators = f } } -// 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]) { +func WithNewConsensusPayload[H Hash](f func(*Context[H], MessageType, any) ConsensusPayload[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewConsensusPayload = f } } // 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]) { - return func(cfg *Config[H, A]) { +func WithNewPrepareRequest[H Hash](f func(ts uint64, nonce uint64, transactionsHashes []H) PrepareRequest[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewPrepareRequest = f } } // WithNewPrepareResponse sets NewPrepareResponse. -func WithNewPrepareResponse[H Hash, A Address](f func(preparationHash H) PrepareResponse[H]) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithNewPrepareResponse[H Hash](f func(preparationHash H) PrepareResponse[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewPrepareResponse = f } } // WithNewChangeView sets NewChangeView. -func WithNewChangeView[H Hash, A Address](f func(byte, ChangeViewReason, uint64) ChangeView) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithNewChangeView[H Hash](f func(byte, ChangeViewReason, uint64) ChangeView) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewChangeView = f } } // WithNewCommit sets NewCommit. -func WithNewCommit[H Hash, A Address](f func([]byte) Commit) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithNewCommit[H Hash](f func([]byte) Commit) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewCommit = f } } // WithNewRecoveryRequest sets NewRecoveryRequest. -func WithNewRecoveryRequest[H Hash, A Address](f func(ts uint64) RecoveryRequest) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithNewRecoveryRequest[H Hash](f func(ts uint64) RecoveryRequest) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewRecoveryRequest = f } } // WithNewRecoveryMessage sets NewRecoveryMessage. -func WithNewRecoveryMessage[H Hash, A Address](f func() RecoveryMessage[H, A]) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithNewRecoveryMessage[H Hash](f func() RecoveryMessage[H]) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.NewRecoveryMessage = f } } // WithVerifyPrepareRequest sets VerifyPrepareRequest. -func WithVerifyPrepareRequest[H Hash, A Address](f func(ConsensusPayload[H, A]) error) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithVerifyPrepareRequest[H Hash](f func(ConsensusPayload[H]) error) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.VerifyPrepareRequest = f } } // WithVerifyPrepareResponse sets VerifyPrepareResponse. -func WithVerifyPrepareResponse[H Hash, A Address](f func(ConsensusPayload[H, A]) error) func(config *Config[H, A]) { - return func(cfg *Config[H, A]) { +func WithVerifyPrepareResponse[H Hash](f func(ConsensusPayload[H]) error) func(config *Config[H]) { + return func(cfg *Config[H]) { cfg.VerifyPrepareResponse = f } } diff --git a/consensus_message.go b/consensus_message.go index 7e72029f..d8859dea 100644 --- a/consensus_message.go +++ b/consensus_message.go @@ -1,7 +1,7 @@ package dbft // ConsensusMessage is an interface for generic dBFT message. -type ConsensusMessage[H Hash, A Address] interface { +type ConsensusMessage[H Hash] interface { // ViewNumber returns view number when this message was originated. ViewNumber() byte // Type returns type of this message. @@ -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. @@ -20,5 +20,5 @@ type ConsensusMessage[H Hash, A Address] interface { // GetRecoveryRequest returns payload as if it was RecoveryRequest. GetRecoveryRequest() RecoveryRequest // GetRecoveryMessage returns payload as if it was RecoveryMessage. - GetRecoveryMessage() RecoveryMessage[H, A] + GetRecoveryMessage() RecoveryMessage[H] } diff --git a/consensus_payload.go b/consensus_payload.go index e537d3e0..c24699ef 100644 --- a/consensus_payload.go +++ b/consensus_payload.go @@ -2,8 +2,8 @@ package dbft // ConsensusPayload is a generic payload type which is exchanged // between the nodes. -type ConsensusPayload[H Hash, A Address] interface { - ConsensusMessage[H, A] +type ConsensusPayload[H Hash] interface { + ConsensusMessage[H] // ValidatorIndex returns index of validator from which // payload was originated from. diff --git a/context.go b/context.go index a6725649..15eb2b85 100644 --- a/context.go +++ b/context.go @@ -10,17 +10,17 @@ import ( // Context is a main dBFT structure which // contains all information needed for performing transitions. -type Context[H Hash, A Address] struct { +type Context[H Hash] struct { // Config is dBFT's Config instance. - Config *Config[H, A] + Config *Config[H] // Priv is node's private key. Priv PrivateKey // Pub is node's public key. Pub PublicKey - block Block[H, A] - header Block[H, A] + block Block[H] + header Block[H] // blockProcessed denotes whether Config.ProcessBlock callback was called for the current // height. If so, then no second call must happen. After new block is received by the user, // dBFT stops any new transaction or messages processing as far as timeouts handling till @@ -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 @@ -56,18 +54,18 @@ type Context[H Hash, A Address] struct { Transactions map[H]Transaction[H] // PreparationPayloads stores consensus Prepare* payloads for the current epoch. - PreparationPayloads []ConsensusPayload[H, A] + PreparationPayloads []ConsensusPayload[H] // CommitPayloads stores consensus Commit payloads sent throughout all epochs. It // is assumed that valid Commit payload can only be sent once by a single node per // the whole set of consensus epochs for particular block. Invalid commit payloads // are kicked off this list immediately (if PrepareRequest was received for the // current round, so it's possible to verify Commit against it) or stored till // the corresponding PrepareRequest receiving. - CommitPayloads []ConsensusPayload[H, A] + CommitPayloads []ConsensusPayload[H] // ChangeViewPayloads stores consensus ChangeView payloads for the current epoch. - ChangeViewPayloads []ConsensusPayload[H, A] + ChangeViewPayloads []ConsensusPayload[H] // LastChangeViewPayloads stores consensus ChangeView payloads for the last epoch. - LastChangeViewPayloads []ConsensusPayload[H, A] + LastChangeViewPayloads []ConsensusPayload[H] // LastSeenMessage array stores the height of the last seen message, for each validator. // if this node never heard from validator i, LastSeenMessage[i] will be -1. LastSeenMessage []*timer.HV @@ -78,16 +76,16 @@ type Context[H Hash, A Address] struct { } // N returns total number of validators. -func (c *Context[H, A]) N() int { return len(c.Validators) } +func (c *Context[H]) N() int { return len(c.Validators) } // F returns number of validators which can be faulty. -func (c *Context[H, A]) F() int { return (len(c.Validators) - 1) / 3 } +func (c *Context[H]) F() int { return (len(c.Validators) - 1) / 3 } // M returns number of validators which must function correctly. -func (c *Context[H, A]) M() int { return len(c.Validators) - c.F() } +func (c *Context[H]) M() int { return len(c.Validators) - c.F() } // GetPrimaryIndex returns index of a primary node for the specified view. -func (c *Context[H, A]) GetPrimaryIndex(viewNumber byte) uint { +func (c *Context[H]) GetPrimaryIndex(viewNumber byte) uint { p := (int(c.BlockIndex) - int(viewNumber)) % len(c.Validators) if p >= 0 { return uint(p) @@ -97,19 +95,19 @@ func (c *Context[H, A]) GetPrimaryIndex(viewNumber byte) uint { } // IsPrimary returns true iff node is primary for current height and view. -func (c *Context[H, A]) IsPrimary() bool { return c.MyIndex == int(c.PrimaryIndex) } +func (c *Context[H]) IsPrimary() bool { return c.MyIndex == int(c.PrimaryIndex) } // IsBackup returns true iff node is backup for current height and view. -func (c *Context[H, A]) IsBackup() bool { +func (c *Context[H]) IsBackup() bool { return c.MyIndex >= 0 && !c.IsPrimary() } // WatchOnly returns true iff node takes no active part in consensus. -func (c *Context[H, A]) WatchOnly() bool { return c.MyIndex < 0 || c.Config.WatchOnly() } +func (c *Context[H]) WatchOnly() bool { return c.MyIndex < 0 || c.Config.WatchOnly() } // CountCommitted returns number of received Commit messages not only for the current // epoch but also for any other epoch. -func (c *Context[H, A]) CountCommitted() (count int) { +func (c *Context[H]) CountCommitted() (count int) { for i := range c.CommitPayloads { if c.CommitPayloads[i] != nil { count++ @@ -121,7 +119,7 @@ func (c *Context[H, A]) CountCommitted() (count int) { // CountFailed returns number of nodes with which no communication was performed // for this view and that hasn't sent the Commit message at the previous views. -func (c *Context[H, A]) CountFailed() (count int) { +func (c *Context[H]) CountFailed() (count int) { for i, hv := range c.LastSeenMessage { if c.CommitPayloads[i] == nil && (hv == nil || hv.Height < c.BlockIndex || hv.View < c.ViewNumber) { count++ @@ -133,18 +131,18 @@ func (c *Context[H, A]) CountFailed() (count int) { // RequestSentOrReceived returns true iff PrepareRequest // was sent or received for the current epoch. -func (c *Context[H, A]) RequestSentOrReceived() bool { +func (c *Context[H]) RequestSentOrReceived() bool { return c.PreparationPayloads[c.PrimaryIndex] != nil } // ResponseSent returns true iff Prepare* message was sent for the current epoch. -func (c *Context[H, A]) ResponseSent() bool { +func (c *Context[H]) ResponseSent() bool { return !c.WatchOnly() && c.PreparationPayloads[c.MyIndex] != nil } // CommitSent returns true iff Commit message was sent for the current epoch // assuming that the node can't go further than current epoch after commit was sent. -func (c *Context[H, A]) CommitSent() bool { +func (c *Context[H]) CommitSent() bool { return !c.WatchOnly() && c.CommitPayloads[c.MyIndex] != nil } @@ -161,10 +159,10 @@ func (c *Context[H, A]) CommitSent() bool { // several places where the call to CreateBlock happens (one of them is right after // PrepareRequest receiving). Thus, we have a separate Context.blockProcessed field // for the described purpose. -func (c *Context[H, A]) BlockSent() bool { return c.blockProcessed } +func (c *Context[H]) BlockSent() bool { return c.blockProcessed } // ViewChanging returns true iff node is in a process of changing view. -func (c *Context[H, A]) ViewChanging() bool { +func (c *Context[H]) ViewChanging() bool { if c.WatchOnly() { return false } @@ -175,7 +173,7 @@ func (c *Context[H, A]) ViewChanging() bool { } // NotAcceptingPayloadsDueToViewChanging returns true if node should not accept new payloads. -func (c *Context[H, A]) NotAcceptingPayloadsDueToViewChanging() bool { +func (c *Context[H]) NotAcceptingPayloadsDueToViewChanging() bool { return c.ViewChanging() && !c.MoreThanFNodesCommittedOrLost() } @@ -186,11 +184,11 @@ func (c *Context[H, A]) NotAcceptingPayloadsDueToViewChanging() bool { // asking change views loses network or crashes and comes back when nodes are committed in more than one higher // numbered view, it is possible for the node accepting recovery to commit in any of the higher views, thus // potentially splitting nodes among views and stalling the network. -func (c *Context[H, A]) MoreThanFNodesCommittedOrLost() bool { +func (c *Context[H]) MoreThanFNodesCommittedOrLost() bool { return c.CountCommitted()+c.CountFailed() > c.F() } -func (c *Context[H, A]) reset(view byte, ts uint64) { +func (c *Context[H]) reset(view byte, ts uint64) { c.MyIndex = -1 c.lastBlockTimestamp = ts @@ -200,7 +198,7 @@ func (c *Context[H, A]) reset(view byte, ts uint64) { c.Validators = c.Config.GetValidators() n := len(c.Validators) - c.LastChangeViewPayloads = make([]ConsensusPayload[H, A], n) + c.LastChangeViewPayloads = make([]ConsensusPayload[H], n) if c.LastSeenMessage == nil { c.LastSeenMessage = make([]*timer.HV, n) @@ -223,11 +221,11 @@ func (c *Context[H, A]) reset(view byte, ts uint64) { c.header = nil n := len(c.Validators) - c.ChangeViewPayloads = make([]ConsensusPayload[H, A], n) + c.ChangeViewPayloads = make([]ConsensusPayload[H], n) if view == 0 { - c.CommitPayloads = make([]ConsensusPayload[H, A], n) + c.CommitPayloads = make([]ConsensusPayload[H], n) } - c.PreparationPayloads = make([]ConsensusPayload[H, A], n) + c.PreparationPayloads = make([]ConsensusPayload[H], n) c.Transactions = make(map[H]Transaction[H]) c.TransactionHashes = nil @@ -244,7 +242,7 @@ func (c *Context[H, A]) reset(view byte, ts uint64) { } // Fill initializes consensus when node is a speaker. -func (c *Context[H, A]) Fill() { +func (c *Context[H]) Fill() { b := make([]byte, 8) _, err := rand.Read(b) if err != nil { @@ -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 @@ -272,12 +267,12 @@ func (c *Context[H, A]) Fill() { // getTimestamp returns nanoseconds-precision timestamp using // current context config. -func (c *Context[H, A]) getTimestamp() uint64 { +func (c *Context[H]) getTimestamp() uint64 { return uint64(c.Config.Timer.Now().UnixNano()) / c.Config.TimestampIncrement * c.Config.TimestampIncrement } // CreateBlock returns resulting block for the current epoch. -func (c *Context[H, A]) CreateBlock() Block[H, A] { +func (c *Context[H]) CreateBlock() Block[H] { if c.block == nil { if c.block = c.MakeHeader(); c.block == nil { return nil @@ -297,7 +292,7 @@ func (c *Context[H, A]) CreateBlock() Block[H, A] { // MakeHeader returns half-filled block for the current epoch. // All hashable fields will be filled. -func (c *Context[H, A]) MakeHeader() Block[H, A] { +func (c *Context[H]) MakeHeader() Block[H] { if c.header == nil { if !c.RequestSentOrReceived() { return nil @@ -310,6 +305,6 @@ func (c *Context[H, A]) MakeHeader() Block[H, A] { // hasAllTransactions returns true iff all transactions were received // for the proposed block. -func (c *Context[H, A]) hasAllTransactions() bool { +func (c *Context[H]) hasAllTransactions() bool { return len(c.TransactionHashes) == len(c.Transactions) } diff --git a/dbft.go b/dbft.go index 2fec0cd8..26a33cb4 100644 --- a/dbft.go +++ b/dbft.go @@ -13,12 +13,12 @@ type ( // and [Config] (service configuration). Data exposed from these fields // is supposed to be read-only, state is changed via methods of this // structure. - DBFT[H Hash, A Address] struct { - Context[H, A] - Config[H, A] + DBFT[H Hash] struct { + Context[H] + Config[H] *sync.Mutex - cache cache[H, A] + cache cache[H] recovering bool } ) @@ -27,8 +27,8 @@ type ( // using provided options or nil if some of the options are missing or invalid. // H and A generic parameters are used as hash and address representation for // dBFT consensus messages, blocks and transactions. -func New[H Hash, A Address](options ...func(config *Config[H, A])) *DBFT[H, A] { - cfg := defaultConfig[H, A]() +func New[H Hash](options ...func(config *Config[H])) *DBFT[H] { + cfg := defaultConfig[H]() for _, option := range options { option(cfg) @@ -38,10 +38,10 @@ func New[H Hash, A Address](options ...func(config *Config[H, A])) *DBFT[H, A] { return nil } - d := &DBFT[H, A]{ + d := &DBFT[H]{ Mutex: new(sync.Mutex), Config: *cfg, - Context: Context[H, A]{ + Context: Context[H]{ Config: cfg, }, } @@ -49,7 +49,7 @@ func New[H Hash, A Address](options ...func(config *Config[H, A])) *DBFT[H, A] { return d } -func (d *DBFT[H, A]) addTransaction(tx Transaction[H]) { +func (d *DBFT[H]) addTransaction(tx Transaction[H]) { d.Transactions[tx.Hash()] = tx if d.hasAllTransactions() { if d.IsPrimary() || d.Context.WatchOnly() { @@ -69,8 +69,8 @@ func (d *DBFT[H, A]) addTransaction(tx Transaction[H]) { // Start initializes dBFT instance and starts the protocol if node is primary. // It accepts the timestamp of the previous block. It should be called once // per DBFT lifetime. -func (d *DBFT[H, A]) Start(ts uint64) { - d.cache = newCache[H, A]() +func (d *DBFT[H]) Start(ts uint64) { + d.cache = newCache[H]() d.initializeConsensus(0, ts) d.start() } @@ -80,11 +80,11 @@ func (d *DBFT[H, A]) Start(ts uint64) { // after new block is processed by ledger (the block can come from dBFT or be // received by other means). The height is to be derived from the configured // CurrentHeight callback and view will be set to 0. -func (d *DBFT[H, A]) Reset(ts uint64) { +func (d *DBFT[H]) Reset(ts uint64) { d.initializeConsensus(0, ts) } -func (d *DBFT[H, A]) initializeConsensus(view byte, ts uint64) { +func (d *DBFT[H]) initializeConsensus(view byte, ts uint64) { d.reset(view, ts) var role string @@ -137,7 +137,7 @@ func (d *DBFT[H, A]) initializeConsensus(view byte, ts uint64) { } // OnTransaction notifies service about receiving new transaction. -func (d *DBFT[H, A]) OnTransaction(tx Transaction[H]) { +func (d *DBFT[H]) OnTransaction(tx Transaction[H]) { // d.Logger.Debug("OnTransaction", // zap.Bool("backup", d.IsBackup()), // zap.Bool("not_accepting", d.NotAcceptingPayloadsDueToViewChanging()), @@ -169,7 +169,7 @@ func (d *DBFT[H, A]) OnTransaction(tx Transaction[H]) { } // OnTimeout advances state machine as if timeout was fired. -func (d *DBFT[H, A]) OnTimeout(hv timer.HV) { +func (d *DBFT[H]) OnTimeout(hv timer.HV) { if d.Context.WatchOnly() || d.BlockSent() { return } @@ -200,7 +200,7 @@ func (d *DBFT[H, A]) OnTimeout(hv timer.HV) { } // OnReceive advances state machine in accordance with msg. -func (d *DBFT[H, A]) OnReceive(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) OnReceive(msg ConsensusPayload[H]) { if int(msg.ValidatorIndex()) >= len(d.Validators) { d.Logger.Error("too big validator index", zap.Uint16("from", msg.ValidatorIndex())) return @@ -269,7 +269,7 @@ func (d *DBFT[H, A]) OnReceive(msg ConsensusPayload[H, A]) { // start performs initial operations and returns messages to be sent. // It must be called after every height or view increment. -func (d *DBFT[H, A]) start() { +func (d *DBFT[H]) start() { if !d.IsPrimary() { if msgs := d.cache.getHeight(d.BlockIndex); msgs != nil { for _, m := range msgs.prepare { @@ -291,7 +291,7 @@ func (d *DBFT[H, A]) start() { d.sendPrepareRequest() } -func (d *DBFT[H, A]) onPrepareRequest(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) onPrepareRequest(msg ConsensusPayload[H]) { // ignore prepareRequest if we had already received it or // are in process of changing view if d.RequestSentOrReceived() { //|| (d.ViewChanging() && !d.MoreThanFNodesCommittedOrLost()) { @@ -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))) @@ -343,7 +342,7 @@ func (d *DBFT[H, A]) onPrepareRequest(msg ConsensusPayload[H, A]) { d.checkPrepare() } -func (d *DBFT[H, A]) processMissingTx() { +func (d *DBFT[H]) processMissingTx() { missing := make([]H, 0, len(d.TransactionHashes)/2) for _, h := range d.TransactionHashes { @@ -369,16 +368,7 @@ func (d *DBFT[H, A]) processMissingTx() { // the new proposed block, if it's fine it returns true, if something is wrong // with it, it sends a changeView request and returns false. It's only valid to // call it when all transactions for this block are already collected. -func (d *DBFT[H, A]) createAndCheckBlock() bool { - txx := make([]Transaction[H], 0, len(d.TransactionHashes)) - 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 - } +func (d *DBFT[H]) createAndCheckBlock() bool { if b := d.Context.CreateBlock(); !d.VerifyBlock(b) { d.Logger.Warn("proposed block fails verification") d.sendChangeView(CVTxInvalid) @@ -387,7 +377,7 @@ func (d *DBFT[H, A]) createAndCheckBlock() bool { return true } -func (d *DBFT[H, A]) updateExistingPayloads(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) updateExistingPayloads(msg ConsensusPayload[H]) { for i, m := range d.PreparationPayloads { if m != nil && m.Type() == PrepareResponseType { resp := m.GetPrepareResponse() @@ -410,7 +400,7 @@ func (d *DBFT[H, A]) updateExistingPayloads(msg ConsensusPayload[H, A]) { } } -func (d *DBFT[H, A]) onPrepareResponse(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) onPrepareResponse(msg ConsensusPayload[H]) { if d.ViewNumber != msg.ViewNumber() { d.Logger.Debug("ignoring wrong view number", zap.Uint("view", uint(msg.ViewNumber()))) return @@ -462,7 +452,7 @@ func (d *DBFT[H, A]) onPrepareResponse(msg ConsensusPayload[H, A]) { } } -func (d *DBFT[H, A]) onChangeView(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) onChangeView(msg ConsensusPayload[H]) { p := msg.GetChangeView() if p.NewViewNumber() <= d.ViewNumber { @@ -493,7 +483,7 @@ func (d *DBFT[H, A]) onChangeView(msg ConsensusPayload[H, A]) { d.checkChangeView(p.NewViewNumber()) } -func (d *DBFT[H, A]) onCommit(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) onCommit(msg ConsensusPayload[H]) { existing := d.CommitPayloads[msg.ValidatorIndex()] if existing != nil { if existing.Hash() != msg.Hash() { @@ -535,7 +525,7 @@ func (d *DBFT[H, A]) onCommit(msg ConsensusPayload[H, A]) { d.CommitPayloads[msg.ValidatorIndex()] = msg } -func (d *DBFT[H, A]) onRecoveryRequest(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) onRecoveryRequest(msg ConsensusPayload[H]) { if !d.CommitSent() { // Limit recoveries to be sent from no more than F nodes // TODO replace loop with a single if @@ -557,7 +547,7 @@ func (d *DBFT[H, A]) onRecoveryRequest(msg ConsensusPayload[H, A]) { d.sendRecoveryMessage() } -func (d *DBFT[H, A]) onRecoveryMessage(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) onRecoveryMessage(msg ConsensusPayload[H]) { d.Logger.Debug("recovery message received", zap.Any("dump", msg)) var ( @@ -617,7 +607,7 @@ func (d *DBFT[H, A]) onRecoveryMessage(msg ConsensusPayload[H, A]) { } } -func (d *DBFT[H, A]) changeTimer(delay time.Duration) { +func (d *DBFT[H]) changeTimer(delay time.Duration) { d.Logger.Debug("reset timer", zap.Uint32("h", d.BlockIndex), zap.Int("v", int(d.ViewNumber)), @@ -625,7 +615,7 @@ func (d *DBFT[H, A]) changeTimer(delay time.Duration) { d.Timer.Reset(timer.HV{Height: d.BlockIndex, View: d.ViewNumber}, delay) } -func (d *DBFT[H, A]) extendTimer(count time.Duration) { +func (d *DBFT[H]) extendTimer(count time.Duration) { if !d.CommitSent() && !d.ViewChanging() { d.Timer.Extend(count * d.SecondsPerBlock / time.Duration(d.M())) } @@ -633,6 +623,6 @@ func (d *DBFT[H, A]) extendTimer(count time.Duration) { // Header returns current header from context. May be nil in case if no // header is constructed yet. Do not change the resulting header. -func (d *DBFT[H, A]) Header() Block[H, A] { +func (d *DBFT[H]) Header() Block[H] { return d.header } diff --git a/dbft_test.go b/dbft_test.go index abd7a056..48209e9d 100644 --- a/dbft_test.go +++ b/dbft_test.go @@ -15,7 +15,7 @@ import ( "go.uber.org/zap" ) -type Payload = dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] +type Payload = dbft.ConsensusPayload[crypto.Uint256] type testState struct { myIndex int @@ -26,8 +26,8 @@ type testState struct { currHeight uint32 currHash crypto.Uint256 pool *testPool - blocks []dbft.Block[crypto.Uint256, crypto.Uint160] - verify func(b dbft.Block[crypto.Uint256, crypto.Uint160]) bool + blocks []dbft.Block[crypto.Uint256] + verify func(b dbft.Block[crypto.Uint256]) bool } type ( @@ -44,7 +44,7 @@ func TestDBFT_OnStartPrimarySendPrepareRequest(t *testing.T) { t.Run("backup sends nothing on start", func(t *testing.T) { s.currHeight = 0 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) service.Start(0) require.Nil(t, s.tryRecv()) @@ -52,7 +52,7 @@ func TestDBFT_OnStartPrimarySendPrepareRequest(t *testing.T) { t.Run("primary send PrepareRequest on start", func(t *testing.T) { s.currHeight = 1 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) service.Start(0) p := s.tryRecv() @@ -91,7 +91,7 @@ func TestDBFT_SingleNode(t *testing.T) { s := newTestState(0, 1) s.currHeight = 2 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) service.Start(0) p := s.tryRecv() @@ -117,7 +117,7 @@ func TestDBFT_SingleNode(t *testing.T) { func TestDBFT_OnReceiveRequestSendResponse(t *testing.T) { s := newTestState(2, 7) - s.verify = func(b dbft.Block[crypto.Uint256, crypto.Uint160]) bool { + s.verify = func(b dbft.Block[crypto.Uint256]) bool { for _, tx := range b.Transactions() { if tx.(testTx)%10 == 0 { return false @@ -129,7 +129,7 @@ func TestDBFT_OnReceiveRequestSendResponse(t *testing.T) { t.Run("receive request from primary", func(t *testing.T) { s.currHeight = 4 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) txs := []testTx{1} s.pool.Add(txs[0]) @@ -161,7 +161,7 @@ func TestDBFT_OnReceiveRequestSendResponse(t *testing.T) { t.Run("change view on invalid tx", func(t *testing.T) { s.currHeight = 4 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) txs := []testTx{10} service.Start(0) @@ -189,7 +189,7 @@ func TestDBFT_OnReceiveRequestSendResponse(t *testing.T) { t.Run("receive invalid prepare request", func(t *testing.T) { s.currHeight = 4 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) txs := []testTx{1, 2} s.pool.Add(txs[0]) @@ -237,7 +237,7 @@ func TestDBFT_CommitOnTransaction(t *testing.T) { s := newTestState(0, 4) s.currHeight = 1 - srv := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + srv := dbft.New[crypto.Uint256](s.getOptions()...) srv.Start(0) require.Nil(t, s.tryRecv()) @@ -257,7 +257,7 @@ func TestDBFT_CommitOnTransaction(t *testing.T) { privs: s.privs, } s1.pool.Add(tx) - srv1 := dbft.New[crypto.Uint256, crypto.Uint160](s1.getOptions()...) + srv1 := dbft.New[crypto.Uint256](s1.getOptions()...) srv1.Start(0) srv1.OnReceive(req) srv1.OnReceive(s1.getPrepareResponse(1, req.Hash())) @@ -279,7 +279,7 @@ func TestDBFT_OnReceiveCommit(t *testing.T) { s := newTestState(2, 4) t.Run("send commit after enough responses", func(t *testing.T) { s.currHeight = 1 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) service.Start(0) req := s.tryRecv() @@ -339,7 +339,7 @@ func TestDBFT_OnReceiveRecoveryRequest(t *testing.T) { s := newTestState(2, 4) t.Run("send recovery message", func(t *testing.T) { s.currHeight = 1 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) service.Start(0) req := s.tryRecv() @@ -361,7 +361,7 @@ func TestDBFT_OnReceiveRecoveryRequest(t *testing.T) { require.Equal(t, dbft.RecoveryMessageType, rm.Type()) other := s.copyWithIndex(3) - srv2 := dbft.New[crypto.Uint256, crypto.Uint160](other.getOptions()...) + srv2 := dbft.New[crypto.Uint256](other.getOptions()...) srv2.Start(0) srv2.OnReceive(rm) @@ -384,7 +384,7 @@ func TestDBFT_OnReceiveChangeView(t *testing.T) { s := newTestState(2, 4) t.Run("change view correctly", func(t *testing.T) { s.currHeight = 6 - service := dbft.New[crypto.Uint256, crypto.Uint160](s.getOptions()...) + service := dbft.New[crypto.Uint256](s.getOptions()...) service.Start(0) resp := s.getChangeView(1, 1) @@ -411,92 +411,85 @@ func TestDBFT_OnReceiveChangeView(t *testing.T) { func TestDBFT_Invalid(t *testing.T) { t.Run("without keys", func(t *testing.T) { - require.Nil(t, dbft.New[crypto.Uint256, crypto.Uint160]()) + require.Nil(t, dbft.New[crypto.Uint256]()) }) priv, pub := crypto.Generate(rand.Reader) require.NotNil(t, priv) require.NotNil(t, pub) - opts := []func(*dbft.Config[crypto.Uint256, crypto.Uint160]){dbft.WithKeyPair[crypto.Uint256, crypto.Uint160](priv, pub)} + opts := []func(*dbft.Config[crypto.Uint256]){dbft.WithKeyPair[crypto.Uint256](priv, pub)} t.Run("without CurrentHeight", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithCurrentHeight[crypto.Uint256, crypto.Uint160](func() uint32 { return 0 })) + opts = append(opts, dbft.WithCurrentHeight[crypto.Uint256](func() uint32 { return 0 })) t.Run("without CurrentBlockHash", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithCurrentBlockHash[crypto.Uint256, crypto.Uint160](func() crypto.Uint256 { return crypto.Uint256{} })) + opts = append(opts, dbft.WithCurrentBlockHash[crypto.Uint256](func() crypto.Uint256 { return crypto.Uint256{} })) t.Run("without GetValidators", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithGetValidators[crypto.Uint256, crypto.Uint160](func(...dbft.Transaction[crypto.Uint256]) []dbft.PublicKey { + opts = append(opts, dbft.WithGetValidators[crypto.Uint256](func(...dbft.Transaction[crypto.Uint256]) []dbft.PublicKey { return []dbft.PublicKey{pub} })) t.Run("without NewBlockFromContext", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithNewBlockFromContext[crypto.Uint256, crypto.Uint160](func(_ *dbft.Context[crypto.Uint256, crypto.Uint160]) dbft.Block[crypto.Uint256, crypto.Uint160] { + opts = append(opts, dbft.WithNewBlockFromContext[crypto.Uint256](func(_ *dbft.Context[crypto.Uint256]) dbft.Block[crypto.Uint256] { 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...)) }) - opts = append(opts, dbft.WithNewConsensusPayload[crypto.Uint256, crypto.Uint160](func(_ *dbft.Context[crypto.Uint256, crypto.Uint160], _ dbft.MessageType, _ any) dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { + opts = append(opts, dbft.WithNewConsensusPayload[crypto.Uint256](func(_ *dbft.Context[crypto.Uint256], _ dbft.MessageType, _ any) dbft.ConsensusPayload[crypto.Uint256] { return nil })) t.Run("without NewPrepareRequest", func(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](func(uint64, uint64, []crypto.Uint256) dbft.PrepareRequest[crypto.Uint256] { return nil })) t.Run("without NewPrepareResponse", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithNewPrepareResponse[crypto.Uint256, crypto.Uint160](func(crypto.Uint256) dbft.PrepareResponse[crypto.Uint256] { + opts = append(opts, dbft.WithNewPrepareResponse[crypto.Uint256](func(crypto.Uint256) dbft.PrepareResponse[crypto.Uint256] { return nil })) t.Run("without NewChangeView", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithNewChangeView[crypto.Uint256, crypto.Uint160](func(byte, dbft.ChangeViewReason, uint64) dbft.ChangeView { + opts = append(opts, dbft.WithNewChangeView[crypto.Uint256](func(byte, dbft.ChangeViewReason, uint64) dbft.ChangeView { return nil })) t.Run("without NewCommit", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithNewCommit[crypto.Uint256, crypto.Uint160](func([]byte) dbft.Commit { + opts = append(opts, dbft.WithNewCommit[crypto.Uint256](func([]byte) dbft.Commit { return nil })) t.Run("without NewRecoveryRequest", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithNewRecoveryRequest[crypto.Uint256, crypto.Uint160](func(uint64) dbft.RecoveryRequest { + opts = append(opts, dbft.WithNewRecoveryRequest[crypto.Uint256](func(uint64) dbft.RecoveryRequest { return nil })) t.Run("without NewRecoveryMessage", func(t *testing.T) { require.Nil(t, dbft.New(opts...)) }) - opts = append(opts, dbft.WithNewRecoveryMessage[crypto.Uint256, crypto.Uint160](func() dbft.RecoveryMessage[crypto.Uint256, crypto.Uint160] { + opts = append(opts, dbft.WithNewRecoveryMessage[crypto.Uint256](func() dbft.RecoveryMessage[crypto.Uint256] { return nil })) t.Run("with all defaults", func(t *testing.T) { @@ -529,19 +522,19 @@ func TestDBFT_Invalid(t *testing.T) { func TestDBFT_FourGoodNodesDeadlock(t *testing.T) { r0 := newTestState(0, 4) r0.currHeight = 4 - s0 := dbft.New[crypto.Uint256, crypto.Uint160](r0.getOptions()...) + s0 := dbft.New[crypto.Uint256](r0.getOptions()...) s0.Start(0) r1 := r0.copyWithIndex(1) - s1 := dbft.New[crypto.Uint256, crypto.Uint160](r1.getOptions()...) + s1 := dbft.New[crypto.Uint256](r1.getOptions()...) s1.Start(0) r2 := r0.copyWithIndex(2) - s2 := dbft.New[crypto.Uint256, crypto.Uint160](r2.getOptions()...) + s2 := dbft.New[crypto.Uint256](r2.getOptions()...) s2.Start(0) r3 := r0.copyWithIndex(3) - s3 := dbft.New[crypto.Uint256, crypto.Uint160](r3.getOptions()...) + s3 := dbft.New[crypto.Uint256](r3.getOptions()...) s3.Start(0) // Step 1. The primary (at view 0) replica 1 sends the PrepareRequest message. @@ -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 @@ -789,7 +782,7 @@ func (s *testState) tryRecv() Payload { return p } -func (s *testState) nextBlock() dbft.Block[crypto.Uint256, crypto.Uint160] { +func (s *testState) nextBlock() dbft.Block[crypto.Uint256] { if len(s.blocks) == 0 { return nil } @@ -812,43 +805,38 @@ 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 }), - dbft.WithCurrentBlockHash[crypto.Uint256, crypto.Uint160](func() crypto.Uint256 { return s.currHash }), - dbft.WithGetValidators[crypto.Uint256, crypto.Uint160](func(...dbft.Transaction[crypto.Uint256]) []dbft.PublicKey { return s.pubs }), - dbft.WithKeyPair[crypto.Uint256, crypto.Uint160](s.privs[s.myIndex], s.pubs[s.myIndex]), - 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()), - dbft.WithLogger[crypto.Uint256, crypto.Uint160](zap.NewNop()), - dbft.WithNewBlockFromContext[crypto.Uint256, crypto.Uint160](newBlockFromContext), - dbft.WithSecondsPerBlock[crypto.Uint256, crypto.Uint160](time.Second * 10), - dbft.WithRequestTx[crypto.Uint256, crypto.Uint160](func(...crypto.Uint256) {}), - dbft.WithGetVerified[crypto.Uint256, crypto.Uint160](func() []dbft.Transaction[crypto.Uint256] { return []dbft.Transaction[crypto.Uint256]{} }), - - dbft.WithNewConsensusPayload[crypto.Uint256, crypto.Uint160](newConsensusPayload), - dbft.WithNewPrepareRequest[crypto.Uint256, crypto.Uint160](payload.NewPrepareRequest), - dbft.WithNewPrepareResponse[crypto.Uint256, crypto.Uint160](payload.NewPrepareResponse), - dbft.WithNewChangeView[crypto.Uint256, crypto.Uint160](payload.NewChangeView), - dbft.WithNewCommit[crypto.Uint256, crypto.Uint160](payload.NewCommit), - dbft.WithNewRecoveryRequest[crypto.Uint256, crypto.Uint160](payload.NewRecoveryRequest), - dbft.WithNewRecoveryMessage[crypto.Uint256, crypto.Uint160](func() dbft.RecoveryMessage[crypto.Uint256, crypto.Uint160] { +func (s *testState) getOptions() []func(*dbft.Config[crypto.Uint256]) { + opts := []func(*dbft.Config[crypto.Uint256]){ + dbft.WithCurrentHeight[crypto.Uint256](func() uint32 { return s.currHeight }), + dbft.WithCurrentBlockHash[crypto.Uint256](func() crypto.Uint256 { return s.currHash }), + dbft.WithGetValidators[crypto.Uint256](func(...dbft.Transaction[crypto.Uint256]) []dbft.PublicKey { return s.pubs }), + dbft.WithKeyPair[crypto.Uint256](s.privs[s.myIndex], s.pubs[s.myIndex]), + dbft.WithBroadcast[crypto.Uint256](func(p Payload) { s.ch = append(s.ch, p) }), + dbft.WithGetTx[crypto.Uint256](s.pool.Get), + dbft.WithProcessBlock[crypto.Uint256](func(b dbft.Block[crypto.Uint256]) { s.blocks = append(s.blocks, b) }), + dbft.WithWatchOnly[crypto.Uint256](func() bool { return false }), + dbft.WithGetBlock[crypto.Uint256](func(crypto.Uint256) dbft.Block[crypto.Uint256] { return nil }), + dbft.WithTimer[crypto.Uint256](timer.New()), + dbft.WithLogger[crypto.Uint256](zap.NewNop()), + dbft.WithNewBlockFromContext[crypto.Uint256](newBlockFromContext), + dbft.WithSecondsPerBlock[crypto.Uint256](time.Second * 10), + dbft.WithRequestTx[crypto.Uint256](func(...crypto.Uint256) {}), + dbft.WithGetVerified[crypto.Uint256](func() []dbft.Transaction[crypto.Uint256] { return []dbft.Transaction[crypto.Uint256]{} }), + + dbft.WithNewConsensusPayload[crypto.Uint256](newConsensusPayload), + dbft.WithNewPrepareRequest[crypto.Uint256](payload.NewPrepareRequest), + dbft.WithNewPrepareResponse[crypto.Uint256](payload.NewPrepareResponse), + dbft.WithNewChangeView[crypto.Uint256](payload.NewChangeView), + dbft.WithNewCommit[crypto.Uint256](payload.NewCommit), + dbft.WithNewRecoveryRequest[crypto.Uint256](payload.NewRecoveryRequest), + dbft.WithNewRecoveryMessage[crypto.Uint256](func() dbft.RecoveryMessage[crypto.Uint256] { return payload.NewRecoveryMessage(nil) }), } verify := s.verify if verify == nil { - verify = func(dbft.Block[crypto.Uint256, crypto.Uint160]) bool { return true } + verify = func(dbft.Block[crypto.Uint256]) bool { return true } } opts = append(opts, dbft.WithVerifyBlock(verify)) @@ -857,23 +845,23 @@ func (s *testState) getOptions() []func(*dbft.Config[crypto.Uint256, crypto.Uint cfg := zap.NewDevelopmentConfig() cfg.DisableStacktrace = true logger, _ := cfg.Build() - opts = append(opts, dbft.WithLogger[crypto.Uint256, crypto.Uint160](logger)) + opts = append(opts, dbft.WithLogger[crypto.Uint256](logger)) } return opts } -func newBlockFromContext(ctx *dbft.Context[crypto.Uint256, crypto.Uint160]) dbft.Block[crypto.Uint256, crypto.Uint160] { +func newBlockFromContext(ctx *dbft.Context[crypto.Uint256]) dbft.Block[crypto.Uint256] { 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 } // newConsensusPayload is a function for creating consensus payload of specific // type. -func newConsensusPayload(c *dbft.Context[crypto.Uint256, crypto.Uint160], t dbft.MessageType, msg any) dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { +func newConsensusPayload(c *dbft.Context[crypto.Uint256], t dbft.MessageType, msg any) dbft.ConsensusPayload[crypto.Uint256] { cp := payload.NewConsensusPayload(t, c.BlockIndex, uint16(c.MyIndex), c.ViewNumber, msg) return cp } diff --git a/helpers.go b/helpers.go index eff55904..21f34e32 100644 --- a/helpers.go +++ b/helpers.go @@ -2,34 +2,34 @@ package dbft type ( // inbox is a structure storing messages from a single epoch. - inbox[H Hash, A Address] struct { - prepare map[uint16]ConsensusPayload[H, A] - chViews map[uint16]ConsensusPayload[H, A] - commit map[uint16]ConsensusPayload[H, A] + inbox[H Hash] struct { + prepare map[uint16]ConsensusPayload[H] + chViews map[uint16]ConsensusPayload[H] + commit map[uint16]ConsensusPayload[H] } // cache is an auxiliary structure storing messages // from future epochs. - cache[H Hash, A Address] struct { - mail map[uint32]*inbox[H, A] + cache[H Hash] struct { + mail map[uint32]*inbox[H] } ) -func newInbox[H Hash, A Address]() *inbox[H, A] { - return &inbox[H, A]{ - prepare: make(map[uint16]ConsensusPayload[H, A]), - chViews: make(map[uint16]ConsensusPayload[H, A]), - commit: make(map[uint16]ConsensusPayload[H, A]), +func newInbox[H Hash]() *inbox[H] { + return &inbox[H]{ + prepare: make(map[uint16]ConsensusPayload[H]), + chViews: make(map[uint16]ConsensusPayload[H]), + commit: make(map[uint16]ConsensusPayload[H]), } } -func newCache[H Hash, A Address]() cache[H, A] { - return cache[H, A]{ - mail: make(map[uint32]*inbox[H, A]), +func newCache[H Hash]() cache[H] { + return cache[H]{ + mail: make(map[uint32]*inbox[H]), } } -func (c *cache[H, A]) getHeight(h uint32) *inbox[H, A] { +func (c *cache[H]) getHeight(h uint32) *inbox[H] { if m, ok := c.mail[h]; ok { delete(c.mail, h) return m @@ -38,10 +38,10 @@ func (c *cache[H, A]) getHeight(h uint32) *inbox[H, A] { return nil } -func (c *cache[H, A]) addMessage(m ConsensusPayload[H, A]) { +func (c *cache[H]) addMessage(m ConsensusPayload[H]) { msgs, ok := c.mail[m.Height()] if !ok { - msgs = newInbox[H, A]() + msgs = newInbox[H]() c.mail[m.Height()] = msgs } diff --git a/helpers_test.go b/helpers_test.go index a24f86db..33a60920 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -9,7 +9,6 @@ import ( // Structures used for type-specific dBFT/payloads implementation to avoid cyclic // dependency. type ( - address struct{} hash struct{} payloadStub struct { height uint32 @@ -22,10 +21,6 @@ func (hash) String() string { return "" } -func (address) String() string { - return "" -} - func (p payloadStub) ViewNumber() byte { panic("TODO") } @@ -47,7 +42,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] { @@ -59,7 +54,7 @@ func (p payloadStub) GetCommit() Commit { func (p payloadStub) GetRecoveryRequest() RecoveryRequest { panic("TODO") } -func (p payloadStub) GetRecoveryMessage() RecoveryMessage[hash, address] { +func (p payloadStub) GetRecoveryMessage() RecoveryMessage[hash] { panic("TODO") } func (p payloadStub) ValidatorIndex() uint16 { @@ -79,7 +74,7 @@ func (p payloadStub) Hash() hash { } func TestMessageCache(t *testing.T) { - c := newCache[hash, address]() + c := newCache[hash]() p1 := payloadStub{ height: 3, diff --git a/identity.go b/identity.go index 420dc361..8ab67b81 100644 --- a/identity.go +++ b/identity.go @@ -31,14 +31,4 @@ type ( comparable fmt.Stringer } - - // Address is a generic address interface used by dbft for operations related - // to consensus address. It is recommended to implement this interface - // using hash functions with low hash collision probability. The following - // requirements must be met: - // 1. Addresses of two equal sets of consensus members are equal. - // 2. Addresses of two different sets of consensus members are different. - Address interface { - comparable - } ) diff --git a/internal/block/block.go b/internal/block/block.go index 19940e7d..ddbf4266 100644 --- a/internal/block/block.go +++ b/internal/block/block.go @@ -52,11 +52,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 @@ -78,11 +73,14 @@ 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] { block := new(neoBlock) block.base.Timestamp = uint32(timestamp / 1000000000) block.base.Index = index - block.base.NextConsensus = nextConsensus + // NextConsensus information is not provided by dBFT context, it's an implementation-specific field, + // and thus, should be managed outside the dBFT library. For simulation simplicity, let's assume + // that NextConsensus is filled by every CN separately and is not verified. + block.base.NextConsensus = crypto.Uint160{1, 2, 3} block.base.PrevHash = prevHash block.base.Version = version block.base.ConsensusData = nonce diff --git a/internal/block/block_test.go b/internal/block/block_test.go index 25e27e86..96f98035 100644 --- a/internal/block/block_test.go +++ b/internal/block/block_test.go @@ -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()) diff --git a/internal/payload/consensus_message.go b/internal/payload/consensus_message.go index dd0e2436..f0285aa7 100644 --- a/internal/payload/consensus_message.go +++ b/internal/payload/consensus_message.go @@ -31,7 +31,7 @@ type ( } ) -var _ dbft.ConsensusMessage[crypto.Uint256, crypto.Uint160] = (*message)(nil) +var _ dbft.ConsensusMessage[crypto.Uint256] = (*message)(nil) // EncodeBinary implements Serializable interface. func (m message) EncodeBinary(w *gob.Encoder) error { @@ -81,16 +81,16 @@ 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]) } func (m message) GetCommit() dbft.Commit { return m.payload.(dbft.Commit) } func (m message) GetRecoveryRequest() dbft.RecoveryRequest { return m.payload.(dbft.RecoveryRequest) } -func (m message) GetRecoveryMessage() dbft.RecoveryMessage[crypto.Uint256, crypto.Uint160] { - return m.payload.(dbft.RecoveryMessage[crypto.Uint256, crypto.Uint160]) +func (m message) GetRecoveryMessage() dbft.RecoveryMessage[crypto.Uint256] { + return m.payload.(dbft.RecoveryMessage[crypto.Uint256]) } // ViewNumber implements ConsensusMessage interface. diff --git a/internal/payload/constructors.go b/internal/payload/constructors.go index 68f19fe7..712b13dd 100644 --- a/internal/payload/constructors.go +++ b/internal/payload/constructors.go @@ -6,7 +6,7 @@ import ( ) // NewConsensusPayload returns minimal ConsensusPayload implementation. -func NewConsensusPayload(t dbft.MessageType, height uint32, validatorIndex uint16, viewNumber byte, consensusMessage any) dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { +func NewConsensusPayload(t dbft.MessageType, height uint32, validatorIndex uint16, viewNumber byte, consensusMessage any) dbft.ConsensusPayload[crypto.Uint256] { return &Payload{ message: message{ cmType: t, @@ -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, } } @@ -58,7 +57,7 @@ func NewRecoveryRequest(ts uint64) dbft.RecoveryRequest { } // NewRecoveryMessage returns minimal RecoveryMessage implementation. -func NewRecoveryMessage(preparationHash *crypto.Uint256) dbft.RecoveryMessage[crypto.Uint256, crypto.Uint160] { +func NewRecoveryMessage(preparationHash *crypto.Uint256) dbft.RecoveryMessage[crypto.Uint256] { return &recoveryMessage{ preparationHash: preparationHash, preparationPayloads: make([]preparationCompact, 0), diff --git a/internal/payload/message.go b/internal/payload/message.go index a39c49a4..b11f4127 100644 --- a/internal/payload/message.go +++ b/internal/payload/message.go @@ -32,7 +32,7 @@ type ( } ) -var _ dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] = (*Payload)(nil) +var _ dbft.ConsensusPayload[crypto.Uint256] = (*Payload)(nil) // EncodeBinary implements Serializable interface. func (p Payload) EncodeBinary(w *gob.Encoder) error { diff --git a/internal/payload/message_test.go b/internal/payload/message_test.go index 59fc44a6..aa764a64 100644 --- a/internal/payload/message_test.go +++ b/internal/payload/message_test.go @@ -107,11 +107,11 @@ func TestRecoveryMessage_NoPayloads(t *testing.T) { rec := m.GetRecoveryMessage() require.NotNil(t, rec) - var p dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] + var p dbft.ConsensusPayload[crypto.Uint256] require.NotPanics(t, func() { p = rec.GetPrepareRequest(p, validators, 0) }) require.Nil(t, p) - var ps []dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] + var ps []dbft.ConsensusPayload[crypto.Uint256] require.NotPanics(t, func() { ps = rec.GetPrepareResponses(p, validators) }) require.Len(t, ps, 0) diff --git a/internal/payload/prepare_request.go b/internal/payload/prepare_request.go index 1fffb097..2c67f670 100644 --- a/internal/payload/prepare_request.go +++ b/internal/payload/prepare_request.go @@ -12,18 +12,16 @@ 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 { @@ -31,7 +29,6 @@ func (p prepareRequest) EncodeBinary(w *gob.Encoder) error { TransactionHashes: p.transactionHashes, Nonce: p.nonce, Timestamp: p.timestamp, - NextConsensus: p.nextConsensus, }) } @@ -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 } @@ -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 -} diff --git a/internal/payload/recovery_message.go b/internal/payload/recovery_message.go index f98647f3..20831564 100644 --- a/internal/payload/recovery_message.go +++ b/internal/payload/recovery_message.go @@ -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 { @@ -24,7 +24,7 @@ type ( } ) -var _ dbft.RecoveryMessage[crypto.Uint256, crypto.Uint160] = (*recoveryMessage)(nil) +var _ dbft.RecoveryMessage[crypto.Uint256] = (*recoveryMessage)(nil) // PreparationHash implements RecoveryMessage interface. func (m *recoveryMessage) PreparationHash() *crypto.Uint256 { @@ -32,7 +32,7 @@ func (m *recoveryMessage) PreparationHash() *crypto.Uint256 { } // AddPayload implements RecoveryMessage interface. -func (m *recoveryMessage) AddPayload(p dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160]) { +func (m *recoveryMessage) AddPayload(p dbft.ConsensusPayload[crypto.Uint256]) { switch p.Type() { case dbft.PrepareRequestType: m.prepareRequest = p.GetPrepareRequest() @@ -58,7 +58,7 @@ func (m *recoveryMessage) AddPayload(p dbft.ConsensusPayload[crypto.Uint256, cry } } -func fromPayload(t dbft.MessageType, recovery dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], p Serializable) *Payload { +func fromPayload(t dbft.MessageType, recovery dbft.ConsensusPayload[crypto.Uint256], p Serializable) *Payload { return &Payload{ message: message{ cmType: t, @@ -70,7 +70,7 @@ func fromPayload(t dbft.MessageType, recovery dbft.ConsensusPayload[crypto.Uint2 } // GetPrepareRequest implements RecoveryMessage interface. -func (m *recoveryMessage) GetPrepareRequest(p dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], _ []dbft.PublicKey, ind uint16) dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { +func (m *recoveryMessage) GetPrepareRequest(p dbft.ConsensusPayload[crypto.Uint256], _ []dbft.PublicKey, ind uint16) dbft.ConsensusPayload[crypto.Uint256] { if m.prepareRequest == nil { return nil } @@ -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) @@ -88,12 +87,12 @@ func (m *recoveryMessage) GetPrepareRequest(p dbft.ConsensusPayload[crypto.Uint2 } // GetPrepareResponses implements RecoveryMessage interface. -func (m *recoveryMessage) GetPrepareResponses(p dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], _ []dbft.PublicKey) []dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { +func (m *recoveryMessage) GetPrepareResponses(p dbft.ConsensusPayload[crypto.Uint256], _ []dbft.PublicKey) []dbft.ConsensusPayload[crypto.Uint256] { if m.preparationHash == nil { return nil } - payloads := make([]dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], len(m.preparationPayloads)) + payloads := make([]dbft.ConsensusPayload[crypto.Uint256], len(m.preparationPayloads)) for i, resp := range m.preparationPayloads { payloads[i] = fromPayload(dbft.PrepareResponseType, p, &prepareResponse{ @@ -106,8 +105,8 @@ func (m *recoveryMessage) GetPrepareResponses(p dbft.ConsensusPayload[crypto.Uin } // GetChangeViews implements RecoveryMessage interface. -func (m *recoveryMessage) GetChangeViews(p dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], _ []dbft.PublicKey) []dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { - payloads := make([]dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], len(m.changeViewPayloads)) +func (m *recoveryMessage) GetChangeViews(p dbft.ConsensusPayload[crypto.Uint256], _ []dbft.PublicKey) []dbft.ConsensusPayload[crypto.Uint256] { + payloads := make([]dbft.ConsensusPayload[crypto.Uint256], len(m.changeViewPayloads)) for i, cv := range m.changeViewPayloads { payloads[i] = fromPayload(dbft.ChangeViewType, p, &changeView{ @@ -121,8 +120,8 @@ func (m *recoveryMessage) GetChangeViews(p dbft.ConsensusPayload[crypto.Uint256, } // GetCommits implements RecoveryMessage interface. -func (m *recoveryMessage) GetCommits(p dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], _ []dbft.PublicKey) []dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { - payloads := make([]dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], len(m.commitPayloads)) +func (m *recoveryMessage) GetCommits(p dbft.ConsensusPayload[crypto.Uint256], _ []dbft.PublicKey) []dbft.ConsensusPayload[crypto.Uint256] { + payloads := make([]dbft.ConsensusPayload[crypto.Uint256], len(m.commitPayloads)) for i, c := range m.commitPayloads { payloads[i] = fromPayload(dbft.CommitType, p, &commit{signature: c.Signature}) diff --git a/internal/simulation/main.go b/internal/simulation/main.go index 8cc655db..387007f3 100644 --- a/internal/simulation/main.go +++ b/internal/simulation/main.go @@ -27,8 +27,8 @@ import ( type ( simNode struct { id int - d *dbft.DBFT[crypto.Uint256, crypto.Uint160] - messages chan dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] + d *dbft.DBFT[crypto.Uint256] + messages chan dbft.ConsensusPayload[crypto.Uint256] key dbft.PrivateKey pub dbft.PublicKey pool *memPool @@ -110,17 +110,17 @@ func initNodes(nodes []*simNode, log *zap.Logger) { } } -func newBlockFromContext(ctx *dbft.Context[crypto.Uint256, crypto.Uint160]) dbft.Block[crypto.Uint256, crypto.Uint160] { +func newBlockFromContext(ctx *dbft.Context[crypto.Uint256]) dbft.Block[crypto.Uint256] { 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 } // defaultNewConsensusPayload is default function for creating // consensus payload of specific type. -func defaultNewConsensusPayload(c *dbft.Context[crypto.Uint256, crypto.Uint160], t dbft.MessageType, msg any) dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160] { +func defaultNewConsensusPayload(c *dbft.Context[crypto.Uint256], t dbft.MessageType, msg any) dbft.ConsensusPayload[crypto.Uint256] { return payload.NewConsensusPayload(t, c.BlockIndex, uint16(c.MyIndex), c.ViewNumber, msg) } @@ -128,7 +128,7 @@ func initSimNode(nodes []*simNode, i int, log *zap.Logger) error { key, pub := crypto.Generate(rand.Reader) nodes[i] = &simNode{ id: i, - messages: make(chan dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160], defaultChanSize), + messages: make(chan dbft.ConsensusPayload[crypto.Uint256], defaultChanSize), key: key, pub: pub, pool: newMemoryPool(), @@ -136,31 +136,30 @@ func initSimNode(nodes []*simNode, i int, log *zap.Logger) error { cluster: nodes, } - nodes[i].d = dbft.New[crypto.Uint256, crypto.Uint160]( - dbft.WithLogger[crypto.Uint256, crypto.Uint160](nodes[i].log), - dbft.WithSecondsPerBlock[crypto.Uint256, crypto.Uint160](time.Second*5), - dbft.WithKeyPair[crypto.Uint256, crypto.Uint160](key, pub), - dbft.WithGetTx[crypto.Uint256, crypto.Uint160](nodes[i].pool.Get), - dbft.WithGetVerified[crypto.Uint256, crypto.Uint160](nodes[i].pool.GetVerified), - dbft.WithBroadcast[crypto.Uint256, crypto.Uint160](nodes[i].Broadcast), - dbft.WithProcessBlock[crypto.Uint256, crypto.Uint160](nodes[i].ProcessBlock), - dbft.WithCurrentHeight[crypto.Uint256, crypto.Uint160](nodes[i].CurrentHeight), - dbft.WithCurrentBlockHash[crypto.Uint256, crypto.Uint160](nodes[i].CurrentBlockHash), - dbft.WithGetValidators[crypto.Uint256, crypto.Uint160](nodes[i].GetValidators), - dbft.WithVerifyPrepareRequest[crypto.Uint256, crypto.Uint160](nodes[i].VerifyPayload), - 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), - dbft.WithNewChangeView[crypto.Uint256, crypto.Uint160](payload.NewChangeView), - dbft.WithNewCommit[crypto.Uint256, crypto.Uint160](payload.NewCommit), - dbft.WithNewRecoveryMessage[crypto.Uint256, crypto.Uint160](func() dbft.RecoveryMessage[crypto.Uint256, crypto.Uint160] { + nodes[i].d = dbft.New[crypto.Uint256]( + dbft.WithLogger[crypto.Uint256](nodes[i].log), + dbft.WithSecondsPerBlock[crypto.Uint256](time.Second*5), + dbft.WithKeyPair[crypto.Uint256](key, pub), + dbft.WithGetTx[crypto.Uint256](nodes[i].pool.Get), + dbft.WithGetVerified[crypto.Uint256](nodes[i].pool.GetVerified), + dbft.WithBroadcast[crypto.Uint256](nodes[i].Broadcast), + dbft.WithProcessBlock[crypto.Uint256](nodes[i].ProcessBlock), + dbft.WithCurrentHeight[crypto.Uint256](nodes[i].CurrentHeight), + dbft.WithCurrentBlockHash[crypto.Uint256](nodes[i].CurrentBlockHash), + dbft.WithGetValidators[crypto.Uint256](nodes[i].GetValidators), + dbft.WithVerifyPrepareRequest[crypto.Uint256](nodes[i].VerifyPayload), + dbft.WithVerifyPrepareResponse[crypto.Uint256](nodes[i].VerifyPayload), + + dbft.WithNewBlockFromContext[crypto.Uint256](newBlockFromContext), + dbft.WithNewConsensusPayload[crypto.Uint256](defaultNewConsensusPayload), + dbft.WithNewPrepareRequest[crypto.Uint256](payload.NewPrepareRequest), + dbft.WithNewPrepareResponse[crypto.Uint256](payload.NewPrepareResponse), + dbft.WithNewChangeView[crypto.Uint256](payload.NewChangeView), + dbft.WithNewCommit[crypto.Uint256](payload.NewCommit), + dbft.WithNewRecoveryMessage[crypto.Uint256](func() dbft.RecoveryMessage[crypto.Uint256] { return payload.NewRecoveryMessage(nil) }), - dbft.WithNewRecoveryRequest[crypto.Uint256, crypto.Uint160](payload.NewRecoveryRequest), + dbft.WithNewRecoveryRequest[crypto.Uint256](payload.NewRecoveryRequest), ) if nodes[i].d == nil { @@ -193,7 +192,7 @@ func sortValidators(pubs []dbft.PublicKey) { }) } -func (n *simNode) Broadcast(m dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160]) { +func (n *simNode) Broadcast(m dbft.ConsensusPayload[crypto.Uint256]) { for i, node := range n.cluster { if i != n.id { select { @@ -213,7 +212,7 @@ func (n *simNode) GetValidators(...dbft.Transaction[crypto.Uint256]) []dbft.Publ return n.validators } -func (n *simNode) ProcessBlock(b dbft.Block[crypto.Uint256, crypto.Uint160]) { +func (n *simNode) ProcessBlock(b dbft.Block[crypto.Uint256]) { n.d.Logger.Debug("received block", zap.Uint32("height", b.Index())) for _, tx := range b.Transactions() { @@ -225,7 +224,7 @@ func (n *simNode) ProcessBlock(b dbft.Block[crypto.Uint256, crypto.Uint160]) { } // VerifyPayload verifies that payload was received from a good validator. -func (n *simNode) VerifyPayload(p dbft.ConsensusPayload[crypto.Uint256, crypto.Uint160]) error { +func (n *simNode) VerifyPayload(p dbft.ConsensusPayload[crypto.Uint256]) error { if *blocked != -1 && p.ValidatorIndex() == uint16(*blocked) { return fmt.Errorf("message from blocked validator: %d", *blocked) } diff --git a/prepare_request.go b/prepare_request.go index c27a2318..3ba594c9 100644 --- a/prepare_request.go +++ b/prepare_request.go @@ -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 } diff --git a/recovery_message.go b/recovery_message.go index 8e6f760d..303ecad0 100644 --- a/recovery_message.go +++ b/recovery_message.go @@ -1,17 +1,17 @@ package dbft // RecoveryMessage represents dBFT Recovery message. -type RecoveryMessage[H Hash, A Address] interface { +type RecoveryMessage[H Hash] interface { // AddPayload adds payload from this epoch to be recovered. - AddPayload(p ConsensusPayload[H, A]) + AddPayload(p ConsensusPayload[H]) // GetPrepareRequest returns PrepareRequest to be processed. - GetPrepareRequest(p ConsensusPayload[H, A], validators []PublicKey, primary uint16) ConsensusPayload[H, A] + GetPrepareRequest(p ConsensusPayload[H], validators []PublicKey, primary uint16) ConsensusPayload[H] // GetPrepareResponses returns a slice of PrepareResponse in any order. - GetPrepareResponses(p ConsensusPayload[H, A], validators []PublicKey) []ConsensusPayload[H, A] + GetPrepareResponses(p ConsensusPayload[H], validators []PublicKey) []ConsensusPayload[H] // GetChangeViews returns a slice of ChangeView in any order. - GetChangeViews(p ConsensusPayload[H, A], validators []PublicKey) []ConsensusPayload[H, A] + GetChangeViews(p ConsensusPayload[H], validators []PublicKey) []ConsensusPayload[H] // GetCommits returns a slice of Commit in any order. - GetCommits(p ConsensusPayload[H, A], validators []PublicKey) []ConsensusPayload[H, A] + GetCommits(p ConsensusPayload[H], validators []PublicKey) []ConsensusPayload[H] // PreparationHash returns has of PrepareRequest payload for this epoch. // It can be useful in case only PrepareResponse payloads were received. diff --git a/send.go b/send.go index 4e32149a..9ab7ac76 100644 --- a/send.go +++ b/send.go @@ -4,7 +4,7 @@ import ( "go.uber.org/zap" ) -func (d *DBFT[H, A]) broadcast(msg ConsensusPayload[H, A]) { +func (d *DBFT[H]) broadcast(msg ConsensusPayload[H]) { d.Logger.Debug("broadcasting message", zap.Stringer("type", msg.Type()), zap.Uint32("height", d.BlockIndex), @@ -14,15 +14,15 @@ func (d *DBFT[H, A]) broadcast(msg ConsensusPayload[H, A]) { d.Broadcast(msg) } -func (c *Context[H, A]) makePrepareRequest() ConsensusPayload[H, A] { +func (c *Context[H]) makePrepareRequest() ConsensusPayload[H] { 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) } -func (d *DBFT[H, A]) sendPrepareRequest() { +func (d *DBFT[H]) sendPrepareRequest() { msg := d.makePrepareRequest() d.PreparationPayloads[d.MyIndex] = msg d.broadcast(msg) @@ -37,7 +37,7 @@ func (d *DBFT[H, A]) sendPrepareRequest() { d.checkPrepare() } -func (c *Context[H, A]) makeChangeView(ts uint64, reason ChangeViewReason) ConsensusPayload[H, A] { +func (c *Context[H]) makeChangeView(ts uint64, reason ChangeViewReason) ConsensusPayload[H] { cv := c.Config.NewChangeView(c.ViewNumber+1, reason, ts) msg := c.Config.NewConsensusPayload(c, ChangeViewType, cv) @@ -46,7 +46,7 @@ func (c *Context[H, A]) makeChangeView(ts uint64, reason ChangeViewReason) Conse return msg } -func (d *DBFT[H, A]) sendChangeView(reason ChangeViewReason) { +func (d *DBFT[H]) sendChangeView(reason ChangeViewReason) { if d.Context.WatchOnly() { return } @@ -83,7 +83,7 @@ func (d *DBFT[H, A]) sendChangeView(reason ChangeViewReason) { d.checkChangeView(newView) } -func (c *Context[H, A]) makePrepareResponse() ConsensusPayload[H, A] { +func (c *Context[H]) makePrepareResponse() ConsensusPayload[H] { resp := c.Config.NewPrepareResponse(c.PreparationPayloads[c.PrimaryIndex].Hash()) msg := c.Config.NewConsensusPayload(c, PrepareResponseType, resp) @@ -92,14 +92,14 @@ func (c *Context[H, A]) makePrepareResponse() ConsensusPayload[H, A] { return msg } -func (d *DBFT[H, A]) sendPrepareResponse() { +func (d *DBFT[H]) sendPrepareResponse() { msg := d.makePrepareResponse() d.Logger.Info("sending PrepareResponse", zap.Uint32("height", d.BlockIndex), zap.Uint("view", uint(d.ViewNumber))) d.StopTxFlow() d.broadcast(msg) } -func (c *Context[H, A]) makeCommit() ConsensusPayload[H, A] { +func (c *Context[H]) makeCommit() ConsensusPayload[H] { if msg := c.CommitPayloads[c.MyIndex]; msg != nil { return msg } @@ -118,14 +118,14 @@ func (c *Context[H, A]) makeCommit() ConsensusPayload[H, A] { return nil } -func (d *DBFT[H, A]) sendCommit() { +func (d *DBFT[H]) sendCommit() { msg := d.makeCommit() d.CommitPayloads[d.MyIndex] = msg d.Logger.Info("sending Commit", zap.Uint32("height", d.BlockIndex), zap.Uint("view", uint(d.ViewNumber))) d.broadcast(msg) } -func (d *DBFT[H, A]) sendRecoveryRequest() { +func (d *DBFT[H]) sendRecoveryRequest() { // If we're here, something is wrong, we either missing some messages or // transactions or both, so re-request missing transactions here too. if d.RequestSentOrReceived() && !d.hasAllTransactions() { @@ -135,7 +135,7 @@ func (d *DBFT[H, A]) sendRecoveryRequest() { d.broadcast(d.Config.NewConsensusPayload(&d.Context, RecoveryRequestType, req)) } -func (c *Context[H, A]) makeRecoveryMessage() ConsensusPayload[H, A] { +func (c *Context[H]) makeRecoveryMessage() ConsensusPayload[H] { recovery := c.Config.NewRecoveryMessage() for _, p := range c.PreparationPayloads { @@ -165,6 +165,6 @@ func (c *Context[H, A]) makeRecoveryMessage() ConsensusPayload[H, A] { return c.Config.NewConsensusPayload(c, RecoveryMessageType, recovery) } -func (d *DBFT[H, A]) sendRecoveryMessage() { +func (d *DBFT[H]) sendRecoveryMessage() { d.broadcast(d.makeRecoveryMessage()) }