OSDN Git Service

modify ci
[bytom/vapor.git] / test / block_test_util.go
1 package test
2
3 import (
4         "encoding/hex"
5
6         "github.com/vapor/consensus"
7         "github.com/vapor/crypto"
8         "github.com/vapor/crypto/ed25519/chainkd"
9         "github.com/vapor/errors"
10         "github.com/vapor/protocol"
11         "github.com/vapor/protocol/bc"
12         "github.com/vapor/protocol/bc/types"
13         "github.com/vapor/protocol/validation"
14         "github.com/vapor/protocol/vm"
15         "github.com/vapor/protocol/vm/vmutil"
16 )
17
18 // NewBlock create block according to the current status of chain
19 func NewBlock(chain *protocol.Chain, txs []*types.Tx, controlProgram []byte) (*types.Block, error) {
20         gasUsed := uint64(0)
21         txsFee := uint64(0)
22         txEntries := []*bc.Tx{nil}
23         txStatus := bc.NewTransactionStatus()
24         if err := txStatus.SetStatus(0, false); err != nil {
25                 return nil, err
26         }
27
28         preBlockHeader := chain.BestBlockHeader()
29
30         b := &types.Block{
31                 BlockHeader: types.BlockHeader{
32                         Version:           1,
33                         Height:            preBlockHeader.Height + 1,
34                         PreviousBlockHash: preBlockHeader.Hash(),
35                         Timestamp:         preBlockHeader.Timestamp + 1,
36                         BlockCommitment:   types.BlockCommitment{},
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         proof, err := generateProof(*b)
73         if err != nil {
74                 return nil, err
75         }
76         b.Proof = proof
77         return b, err
78 }
79
80 func generateProof(block types.Block) (types.Proof, error) {
81         var xPrv chainkd.XPrv
82         if consensus.ActiveNetParams.Signer == "" {
83                 return types.Proof{}, errors.New("Signer is empty")
84         }
85         xPrv.UnmarshalText([]byte(consensus.ActiveNetParams.Signer))
86         sign := xPrv.Sign(block.BlockCommitment.TransactionsMerkleRoot.Bytes())
87         pubHash := crypto.Ripemd160(xPrv.XPub().PublicKey())
88         control, err := vmutil.P2WPKHProgram([]byte(pubHash))
89         if err != nil {
90                 return types.Proof{}, err
91         }
92         return types.Proof{Sign: sign, ControlProgram: control}, nil
93 }
94
95 // ReplaceCoinbase replace the coinbase tx of block with coinbaseTx
96 func ReplaceCoinbase(block *types.Block, coinbaseTx *types.Tx) (err error) {
97         block.Transactions[0] = coinbaseTx
98         txEntires := []*bc.Tx{coinbaseTx.Tx}
99         for i := 1; i < len(block.Transactions); i++ {
100                 txEntires = append(txEntires, block.Transactions[i].Tx)
101         }
102
103         block.TransactionsMerkleRoot, err = types.TxMerkleRoot(txEntires)
104         return
105 }
106
107 // AppendBlocks append empty blocks to chain, mainly used to mature the coinbase tx
108 func AppendBlocks(chain *protocol.Chain, num uint64) error {
109         for i := uint64(0); i < num; i++ {
110                 block, err := NewBlock(chain, nil, []byte{byte(vm.OP_TRUE)})
111                 if err != nil {
112                         return err
113                 }
114                 if err := SolveAndUpdate(chain, block); err != nil {
115                         return err
116                 }
117         }
118         return nil
119 }
120
121 func setAuthoritys(chain *protocol.Chain) {
122         authoritys := make(map[string]string)
123         xpubStr := "96bc2ad4b1c2db399990c811c4367688cbb7867612bb9d04e4dc7848e425c6395264d3b177a96646bc0ce517ae7fd63504c183ab6d330dea184331a4cf5912d5"
124         var xpub chainkd.XPub
125         xpub.UnmarshalText([]byte(xpubStr))
126
127         pubHash := crypto.Ripemd160(xpub.PublicKey())
128         control, _ := vmutil.P2WPKHProgram([]byte(pubHash))
129         key := hex.EncodeToString(control)
130         authoritys[key] = xpub.String()
131
132         chain.SetAuthoritys(authoritys)
133 }
134
135 // SolveAndUpdate solve difficulty and update chain status
136 func SolveAndUpdate(chain *protocol.Chain, block *types.Block) error {
137         _, err := chain.ProcessBlock(block)
138         return err
139 }