Skip to content

Commit a4cea5b

Browse files
authored
Merge pull request #138 from bane-labs/block-verification-t2
dbft: Block verification t2
2 parents eb43be1 + bd8bddc commit a4cea5b

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

consensus/dbft/block.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,11 @@ func (b *Block) Verify(pub crypto.PublicKey, sign []byte) error {
118118
func (b *Block) Hash() util.Uint256 {
119119
return WorkerSealHash(b.header).Uint256()
120120
}
121+
122+
// Convert dbft.Blcok to types.Block
123+
func (b *Block) ToEthBlock() *types.Block {
124+
res := types.NewBlockWithHeader(b.header)
125+
// Uncles are always nil in dBFT-like consensus.
126+
res = res.WithBody(b.transactions, nil)
127+
return res
128+
}

consensus/dbft/chainreader.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type ChainHeaderReader interface {
1515
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
1616
HasBlock(hash common.Hash, number uint64) bool
1717
GetBlockByNumber(uint64) *types.Block
18+
VerifyBlock(block *types.Block) error
1819
}
1920

2021
// ChainHeaderWriter is a Blockchain API abstraction needed for proper blockQueue

consensus/dbft/dbft.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,30 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) {
520520

521521
return nil
522522
}),
523+
dbft.WithVerifyBlock(func(b block.Block) bool {
524+
dbftBlock := b.(*Block)
525+
parent := c.chain.CurrentBlock()
526+
if parent.Number.Cmp(dbftBlock.header.Number) >= 0 {
527+
log.Warn("proposed block has already outdated",
528+
"current block number", parent.Number.Uint64(),
529+
"proposed block number", dbftBlock.header.Number)
530+
return false
531+
}
532+
if c.lastTimestamp > dbftBlock.header.Time {
533+
log.Warn("proposed block has small timestamp",
534+
"ts", dbftBlock.header.Time,
535+
"last", c.lastTimestamp)
536+
return false
537+
}
538+
ethBlock := dbftBlock.ToEthBlock()
539+
err := c.chain.VerifyBlock(ethBlock)
540+
if err != nil {
541+
log.Warn("proposed block verification failed",
542+
"err", err.Error())
543+
return false
544+
}
545+
return true
546+
}),
523547
dbft.WithBroadcast(func(p payload.ConsensusPayload) {
524548
if err := p.(*Payload).Sign(c.dbft.Priv.(*Signer)); err != nil {
525549
log.Warn("can't sign consensus payload", "error", err)

core/blockchain.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,3 +2605,46 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
26052605
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
26062606
return time.Duration(bc.flushInterval.Load())
26072607
}
2608+
2609+
// VerifyBlock checks block state
2610+
func (bc *BlockChain) VerifyBlock(block *types.Block) error {
2611+
err := bc.validator.ValidateBody(block)
2612+
if err != nil {
2613+
err = fmt.Errorf("failed to validate body: %w", err)
2614+
log.Error(err.Error())
2615+
return err
2616+
}
2617+
2618+
parent := bc.GetBlockByHash(block.ParentHash())
2619+
if parent == nil {
2620+
err = fmt.Errorf("failed to retrieve parent by hash to verify block, %s: %v, %s: %s", "parent number", block.NumberU64()-1,
2621+
"parent hash", block.ParentHash().String())
2622+
log.Error(err.Error())
2623+
parent = bc.GetBlockByNumber(block.NumberU64() - 1)
2624+
if parent == nil {
2625+
err = fmt.Errorf("failed to retrieve canonical parent by number to verify block, %s: %v, %s: %s", "parent number", block.NumberU64()-1,
2626+
"parent hash", block.ParentHash().String())
2627+
log.Error(err.Error())
2628+
return err
2629+
}
2630+
}
2631+
statedb, err := bc.StateAt(parent.Root())
2632+
if err != nil {
2633+
err = fmt.Errorf("failed to retrieve state at %s: %w", parent.Root(), err)
2634+
log.Error(err.Error())
2635+
return err
2636+
}
2637+
2638+
receipts, _, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
2639+
if err != nil {
2640+
err = fmt.Errorf("failed to process block: %w", err)
2641+
log.Error(err.Error())
2642+
return err
2643+
}
2644+
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
2645+
err = fmt.Errorf("failed to verify state: %w", err)
2646+
log.Error(err.Error())
2647+
return err
2648+
}
2649+
return nil
2650+
}

0 commit comments

Comments
 (0)