github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/test/block_test_util.go (about)

     1  package test
     2  
     3  import (
     4  	"github.com/bytom/bytom/mining/tensority"
     5  	"github.com/bytom/bytom/protocol"
     6  	"github.com/bytom/bytom/protocol/bc"
     7  	"github.com/bytom/bytom/protocol/bc/types"
     8  	"github.com/bytom/bytom/protocol/validation"
     9  	"github.com/bytom/bytom/protocol/vm"
    10  )
    11  
    12  // NewBlock create block according to the current status of chain
    13  func NewBlock(chain *protocol.Chain, txs []*types.Tx, controlProgram []byte) (*types.Block, error) {
    14  	gasUsed := uint64(0)
    15  	txsFee := uint64(0)
    16  	txEntries := []*bc.Tx{nil}
    17  	txStatus := bc.NewTransactionStatus()
    18  	if err := txStatus.SetStatus(0, false); err != nil {
    19  		return nil, err
    20  	}
    21  
    22  	preBlockHeader := chain.BestBlockHeader()
    23  	preBlockHash := preBlockHeader.Hash()
    24  	nextBits, err := chain.CalcNextBits(&preBlockHash)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	b := &types.Block{
    30  		BlockHeader: types.BlockHeader{
    31  			Version:           1,
    32  			Height:            preBlockHeader.Height + 1,
    33  			PreviousBlockHash: preBlockHeader.Hash(),
    34  			Timestamp:         preBlockHeader.Timestamp + 1,
    35  			BlockCommitment:   types.BlockCommitment{},
    36  			Bits:              nextBits,
    37  		},
    38  		Transactions: []*types.Tx{nil},
    39  	}
    40  
    41  	bcBlock := &bc.Block{BlockHeader: &bc.BlockHeader{Height: preBlockHeader.Height + 1}}
    42  	for _, tx := range txs {
    43  		gasOnlyTx := false
    44  		gasStatus, err := validation.ValidateTx(tx.Tx, bcBlock)
    45  		if err != nil {
    46  			if !gasStatus.GasValid {
    47  				continue
    48  			}
    49  			gasOnlyTx = true
    50  		}
    51  
    52  		txStatus.SetStatus(len(b.Transactions), gasOnlyTx)
    53  		b.Transactions = append(b.Transactions, tx)
    54  		txEntries = append(txEntries, tx.Tx)
    55  		gasUsed += uint64(gasStatus.GasUsed)
    56  		txsFee += txFee(tx)
    57  	}
    58  
    59  	coinbaseTx, err := CreateCoinbaseTx(controlProgram, preBlockHeader.Height+1, txsFee)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	b.Transactions[0] = coinbaseTx
    65  	txEntries[0] = coinbaseTx.Tx
    66  	b.TransactionsMerkleRoot, err = types.TxMerkleRoot(txEntries)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	b.TransactionStatusHash, err = types.TxStatusMerkleRoot(txStatus.VerifyStatus)
    72  	return b, err
    73  }
    74  
    75  // ReplaceCoinbase replace the coinbase tx of block with coinbaseTx
    76  func ReplaceCoinbase(block *types.Block, coinbaseTx *types.Tx) (err error) {
    77  	block.Transactions[0] = coinbaseTx
    78  	txEntires := []*bc.Tx{coinbaseTx.Tx}
    79  	for i := 1; i < len(block.Transactions); i++ {
    80  		txEntires = append(txEntires, block.Transactions[i].Tx)
    81  	}
    82  
    83  	block.TransactionsMerkleRoot, err = types.TxMerkleRoot(txEntires)
    84  	return
    85  }
    86  
    87  // AppendBlocks append empty blocks to chain, mainly used to mature the coinbase tx
    88  func AppendBlocks(chain *protocol.Chain, num uint64) error {
    89  	for i := uint64(0); i < num; i++ {
    90  		block, err := NewBlock(chain, nil, []byte{byte(vm.OP_TRUE)})
    91  		if err != nil {
    92  			return err
    93  		}
    94  		if err := SolveAndUpdate(chain, block); err != nil {
    95  			return err
    96  		}
    97  	}
    98  	return nil
    99  }
   100  
   101  // SolveAndUpdate solve difficulty and update chain status
   102  func SolveAndUpdate(chain *protocol.Chain, block *types.Block) error {
   103  	seed, err := chain.CalcNextSeed(&block.PreviousBlockHash)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	Solve(seed, block)
   108  	_, err = chain.ProcessBlock(block)
   109  	return err
   110  }
   111  
   112  // Solve simulate solve difficulty by add result to cache
   113  func Solve(seed *bc.Hash, block *types.Block) {
   114  	hash := block.BlockHeader.Hash()
   115  	tensority.AIHash.AddCache(&hash, seed, &bc.Hash{})
   116  }