Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions consensus/dbft/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,11 @@ func (b *Block) Verify(pub crypto.PublicKey, sign []byte) error {
func (b *Block) Hash() util.Uint256 {
return WorkerSealHash(b.header).Uint256()
}

// Convert dbft.Blcok to types.Block
func (b *Block) ToEthBlock() *types.Block {
res := types.NewBlockWithHeader(b.header)
// Uncles are always nil in dBFT-like consensus.
res = res.WithBody(b.transactions, nil)
return res
}
1 change: 1 addition & 0 deletions consensus/dbft/chainreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type ChainHeaderReader interface {
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
HasBlock(hash common.Hash, number uint64) bool
GetBlockByNumber(uint64) *types.Block
VerifyBlock(block *types.Block) error
}

// ChainHeaderWriter is a Blockchain API abstraction needed for proper blockQueue
Expand Down
24 changes: 24 additions & 0 deletions consensus/dbft/dbft.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,30 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) {

return nil
}),
dbft.WithVerifyBlock(func(b block.Block) bool {
dbftBlock := b.(*Block)
parent := c.chain.CurrentBlock()
if parent.Number.Cmp(dbftBlock.header.Number) >= 0 {
log.Warn("proposed block has already outdated",
"current block number", parent.Number.Uint64(),
"proposed block number", dbftBlock.header.Number)
return false
}
if c.lastTimestamp > dbftBlock.header.Time {
log.Warn("proposed block has small timestamp",
"ts", dbftBlock.header.Time,
"last", c.lastTimestamp)
return false
}
ethBlock := dbftBlock.ToEthBlock()
err := c.chain.VerifyBlock(ethBlock)
if err != nil {
log.Warn("proposed block verification failed",
"err", err.Error())
return false
}
return true
}),
dbft.WithBroadcast(func(p payload.ConsensusPayload) {
if err := p.(*Payload).Sign(c.dbft.Priv.(*Signer)); err != nil {
log.Warn("can't sign consensus payload", "error", err)
Expand Down
43 changes: 43 additions & 0 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2605,3 +2605,46 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
return time.Duration(bc.flushInterval.Load())
}

// VerifyBlock checks block state
func (bc *BlockChain) VerifyBlock(block *types.Block) error {
err := bc.validator.ValidateBody(block)
if err != nil {
err = fmt.Errorf("failed to validate body: %w", err)
log.Error(err.Error())
return err
}

parent := bc.GetBlockByHash(block.ParentHash())
if parent == nil {
err = fmt.Errorf("failed to retrieve parent by hash to verify block, %s: %v, %s: %s", "parent number", block.NumberU64()-1,
"parent hash", block.ParentHash().String())
log.Error(err.Error())
parent = bc.GetBlockByNumber(block.NumberU64() - 1)
if parent == nil {
err = fmt.Errorf("failed to retrieve canonical parent by number to verify block, %s: %v, %s: %s", "parent number", block.NumberU64()-1,
"parent hash", block.ParentHash().String())
log.Error(err.Error())
return err
}
}
statedb, err := bc.StateAt(parent.Root())
if err != nil {
err = fmt.Errorf("failed to retrieve state at %s: %w", parent.Root(), err)
log.Error(err.Error())
return err
}

receipts, _, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
if err != nil {
err = fmt.Errorf("failed to process block: %w", err)
log.Error(err.Error())
return err
}
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
err = fmt.Errorf("failed to verify state: %w", err)
log.Error(err.Error())
return err
}
return nil
}