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  }