github.com/aergoio/aergo@v1.3.1/chain/blockvalidator.go (about) 1 /** 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package chain 7 8 import ( 9 "bytes" 10 "errors" 11 "github.com/aergoio/aergo/internal/enc" 12 "github.com/aergoio/aergo/pkg/component" 13 "github.com/aergoio/aergo/state" 14 "github.com/aergoio/aergo/types" 15 ) 16 17 type BlockValidator struct { 18 signVerifier *SignVerifier 19 sdb *state.ChainStateDB 20 isNeedWait bool 21 } 22 23 var ( 24 ErrorBlockVerifySign = errors.New("Block verify failed") 25 ErrorBlockVerifyTxRoot = errors.New("Block verify failed, because Tx root hash is invaild") 26 ErrorBlockVerifyExistStateRoot = errors.New("Block verify failed, because state root hash is already exist") 27 ErrorBlockVerifyStateRoot = errors.New("Block verify failed, because state root hash is not equal") 28 ErrorBlockVerifyReceiptRoot = errors.New("Block verify failed, because receipt root hash is not equal") 29 ) 30 31 func NewBlockValidator(comm component.IComponentRequester, sdb *state.ChainStateDB) *BlockValidator { 32 bv := BlockValidator{ 33 signVerifier: NewSignVerifier(comm, sdb, VerifierCount, dfltUseMempool), 34 sdb: sdb, 35 } 36 37 logger.Info().Msg("started signverifier") 38 return &bv 39 } 40 41 func (bv *BlockValidator) Stop() { 42 bv.signVerifier.Stop() 43 } 44 45 func (bv *BlockValidator) ValidateBlock(block *types.Block) error { 46 if err := bv.ValidateHeader(block.GetHeader()); err != nil { 47 return err 48 } 49 50 if err := bv.ValidateBody(block); err != nil { 51 return err 52 } 53 return nil 54 } 55 56 func (bv *BlockValidator) ValidateHeader(header *types.BlockHeader) error { 57 // TODO : more field? 58 // Block, State not exsit 59 // MaxBlockSize 60 // MaxHeaderSize 61 // ChainVersion 62 // StateRootHash 63 if bv.sdb.IsExistState(header.GetBlocksRootHash()) { 64 return ErrorBlockVerifyExistStateRoot 65 } 66 67 return nil 68 } 69 70 func (bv *BlockValidator) ValidateBody(block *types.Block) error { 71 txs := block.GetBody().GetTxs() 72 73 // TxRootHash 74 logger.Debug().Int("Txlen", len(txs)).Str("TxRoot", enc.ToString(block.GetHeader().GetTxsRootHash())). 75 Msg("tx root verify") 76 77 computeTxRootHash := types.CalculateTxsRootHash(txs) 78 if bytes.Equal(block.GetHeader().GetTxsRootHash(), computeTxRootHash) == false { 79 logger.Error().Str("block", block.ID()). 80 Str("txroot", enc.ToString(block.GetHeader().GetTxsRootHash())). 81 Str("compute txroot", enc.ToString(computeTxRootHash)). 82 Msg("tx root validation failed") 83 return ErrorBlockVerifyTxRoot 84 } 85 86 // check Tx sign 87 if len(txs) == 0 { 88 return nil 89 } 90 91 bv.signVerifier.RequestVerifyTxs(&types.TxList{Txs: txs}) 92 bv.isNeedWait = true 93 94 return nil 95 } 96 97 func (bv *BlockValidator) WaitVerifyDone() error { 98 logger.Debug().Bool("need", bv.isNeedWait).Msg("wait to verify tx") 99 100 if !bv.isNeedWait { 101 return nil 102 } 103 bv.isNeedWait = false 104 105 if failed, _ := bv.signVerifier.WaitDone(); failed == true { 106 logger.Error().Msg("sign of txs validation failed") 107 return ErrorBlockVerifySign 108 } 109 110 return nil 111 } 112 113 func (bv *BlockValidator) ValidatePost(sdbRoot []byte, receipts *types.Receipts, block *types.Block) error { 114 hdrRoot := block.GetHeader().GetBlocksRootHash() 115 116 if !bytes.Equal(hdrRoot, sdbRoot) { 117 logger.Error().Str("block", block.ID()). 118 Str("hdrroot", enc.ToString(hdrRoot)). 119 Str("sdbroot", enc.ToString(sdbRoot)). 120 Msg("block root hash validation failed") 121 return ErrorBlockVerifyStateRoot 122 } 123 124 logger.Debug().Str("sdbroot", enc.ToString(sdbRoot)). 125 Msg("block root hash validation succeed") 126 127 hdrRoot = block.GetHeader().ReceiptsRootHash 128 receiptsRoot := receipts.MerkleRoot() 129 if !bytes.Equal(hdrRoot, receiptsRoot) { 130 logger.Error().Str("block", block.ID()). 131 Str("hdrroot", enc.ToString(hdrRoot)). 132 Str("receipts_root", enc.ToString(receiptsRoot)). 133 Msg("receipts root hash validation failed") 134 return ErrorBlockVerifyReceiptRoot 135 } 136 logger.Debug().Str("receipts_root", enc.ToString(receiptsRoot)). 137 Msg("receipt root hash validation succeed") 138 139 return nil 140 }