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 }