github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/validation/validate_block.go (about)

     1  package validation
     2  
     3  import (
     4  	"sort"
     5  
     6  	"fmt"
     7  
     8  	"bytes"
     9  
    10  	"github.com/sixexorg/magnetic-ring/core/mainchain/types"
    11  	"github.com/sixexorg/magnetic-ring/errors"
    12  	"github.com/sixexorg/magnetic-ring/log"
    13  	"github.com/sixexorg/magnetic-ring/store/mainchain/genesis"
    14  	"github.com/sixexorg/magnetic-ring/store/mainchain/storages"
    15  )
    16  
    17  func ValidateBlock(block *types.Block, ledgerStore *storages.LedgerStoreImp) (*storages.BlockInfo, error) {
    18  	/*	for k, v := range block.Transactions {
    19  			fmt.Println("num:", k, ",hash:", v.Hash().String(), ",from:", v.TxData.From.ToString(), ",nonce:", v.TxData.Froms.Tis[0].Nonce)
    20  		}
    21  	*/
    22  	log.Info("func validation ValidateBlock start", "blockHeight", block.Header.Height, "txlen", block.Transactions.Len())
    23  	blockHeight := block.Header.Height
    24  	if ledgerStore.GetCurrentBlockHeight()+1 < blockHeight {
    25  		return nil, errors.ERR_BLOCK_ABNORMAL_HEIGHT
    26  	}
    27  	if blockHeight > 1 {
    28  		prevBlock, err := ledgerStore.GetBlockByHeight(blockHeight - 1)
    29  		if err != nil {
    30  			return nil, err
    31  		}
    32  		if !bytes.Equal(prevBlock.Hash().ToBytes(), block.Header.PrevBlockHash.ToBytes()) {
    33  			return nil, errors.ERR_BLOCK_PREVHASH_DIFF
    34  		}
    35  	}
    36  
    37  	/*	add, _ := common.ToAddress("ct0fHcR19s2nDaHxR3CVdUyYxHgsjzp8wrt")
    38  		acc, err := ledgerStore.GetAccountByHeight(blockHeight, add)
    39  		if err == nil {
    40  			fmt.Println("accountNonce", acc.Data.Nonce)
    41  		}*/
    42  	sv := NewStateValidate(ledgerStore)
    43  	txLen := block.Transactions.Len()
    44  	if txLen > 0 {
    45  		txsch := make(chan *types.Transaction, block.Transactions.Len())
    46  		txs := types.TxByNonce(block.Transactions)
    47  		sort.Sort(txs)
    48  		go func(txs types.TxByNonce) {
    49  			for _, v := range txs {
    50  				txTmp := v
    51  				txsch <- txTmp
    52  			}
    53  		}(txs)
    54  		count := 0
    55  		breakCount := block.Transactions.Len() * block.Transactions.Len()
    56  
    57  		ii := 0
    58  		for txTmp := range txsch {
    59  			count++
    60  			//txTmp := ch
    61  			re, err := sv.VerifyTx(txTmp)
    62  			//fmt.Println("validateBlock verifyTx err:", err, ",hash:", txTmp.Hash().String(), "from:", txTmp.TxData.From.ToString(), "nonce:", txTmp.TxData.Froms.Tis[0].Nonce)
    63  			if re == 0 {
    64  				txsch <- txTmp
    65  			} else if re == -1 {
    66  				return nil, fmt.Errorf("ValidateBlock err:%s,type:%s,result:-1\n", errors.ERR_BLOCK_ABNORMAL_TXS.Error(), err.Error())
    67  			} else if re == 1 {
    68  				ii++
    69  				//fmt.Println("num:", ii, "hash:", ch.Hash().String())
    70  				if ii == block.Transactions.Len() {
    71  					close(txsch)
    72  				}
    73  			}
    74  			if count > breakCount {
    75  				return nil, fmt.Errorf("ValidateBlock err:%s,type:%s\n", errors.ERR_BLOCK_ABNORMAL_TXS.Error(), err.Error())
    76  			}
    77  		}
    78  		//to clear
    79  		if count > breakCount {
    80  			return nil, fmt.Errorf("ValidateBlock err:%s\n", errors.ERR_BLOCK_ABNORMAL_TXS.Error())
    81  		}
    82  	}
    83  	blockInfo := sv.ExecuteOplogs()
    84  	if blockHeight == 1 {
    85  		ass, txs := genesis.GetGenesisBlockState()
    86  		blockInfo.AccountStates = ass
    87  		blockInfo.Block.Header.TxRoot = txs.GetHashRoot()
    88  		blockInfo.Block.Header.StateRoot = blockInfo.AccountStates.GetHashRoot()
    89  		blockInfo.Block.Transactions = txs
    90  	}
    91  
    92  	/*fmt.Printf("blockNew:\n txroot:%s\n receipt:%s\n account:%s\n league:%s\n",
    93  		blockInfo.Block.Header.TxRoot.String(),
    94  		blockInfo.Block.Header.ReceiptsRoot.String(),
    95  		blockInfo.Block.Header.StateRoot.String(),
    96  		blockInfo.Block.Header.LeagueRoot.String(),
    97  	)*/
    98  	/*for k, v := range blockInfo.Receipts {
    99  		fmt.Printf("Receipts2: num:%d, status:%t, txhash:%s, gasused:%d \n", k, v.Status, v.TxHash.String(), v.GasUsed)
   100  	}*/
   101  	/*
   102  		for k, v := range blockInfo.AccountStates {
   103  			fmt.Printf("States2: num:%d, Hash:%s, nonce:%d, balance:%d ,gasBalance:%d \n", k, v.Hash().String(), v.Data.Nonce, v.Data.Balance, v.Data.EnergyBalance)
   104  		}*/
   105  	/*	for k, v := range blockInfo.LeagueStates {
   106  		fmt.Printf("league2: num:%d, address:%s, nonce:%d, MemberRoot:%d, FrozenBox:%d, Private:%t, minBox:%d, rate:%d, creator:%s  ", k, v.Address.ToString(), v.Data.Nonce, v.Data.MemberRoot, v.Data.FrozenBox.Uint64(), v.Data.Private, v.MinBox, v.Rate, v.Creator.ToString())
   107  	}*/
   108  
   109  	log.Info(fmt.Sprintf("func validation ValidateBlock root cmp blocknew : receipt:%s  league:%s state:%s", blockInfo.Block.Header.ReceiptsRoot.String(), blockInfo.Block.Header.LeagueRoot.String(), blockInfo.Block.Header.StateRoot.String()))
   110  	log.Info(fmt.Sprintf("func validation ValidateBlock root cmp blockold : receipt:%s  league:%s state:%s", block.Header.ReceiptsRoot.String(), block.Header.LeagueRoot.String(), block.Header.StateRoot.String()))
   111  	if blockInfo.Block.Header.ReceiptsRoot != block.Header.ReceiptsRoot ||
   112  		blockInfo.Block.Header.LeagueRoot != block.Header.LeagueRoot ||
   113  		blockInfo.Block.Header.StateRoot != block.Header.StateRoot {
   114  		log.Info("func validation ValidateBlock failed", "blockHeight", blockInfo.Block.Header.Height, "txlen", blockInfo.Block.Transactions.Len())
   115  		return nil, errors.ERR_BLOCK_ABNORMAL_TXS
   116  	}
   117  	blockInfo.Block.Header.ConsensusPayload = block.Header.ConsensusPayload
   118  	blockInfo.Block.Header.Timestamp = block.Header.Timestamp
   119  	blockInfo.Block.Sigs = block.Sigs
   120  	blockInfo.Block.Header.ConsensusData = block.Header.ConsensusData
   121  	blockInfo.Block.Header.NextBookkeeper = block.Header.NextBookkeeper
   122  	log.Info("func validation ValidateBlock end", "blockHeight", blockInfo.Block.Header.Height, "txlen", blockInfo.Block.Transactions.Len())
   123  	return blockInfo, nil
   124  }