OSDN Git Service

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