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