OSDN Git Service

f4adecf697b7f2ae2ab94d1c13cca5d989ee2b26
[bytom/vapor.git] / test / mock / chain.go
1 package mock
2
3 import (
4         "errors"
5         "math/rand"
6
7         "github.com/bytom/vapor/protocol"
8         "github.com/bytom/vapor/protocol/bc"
9         "github.com/bytom/vapor/protocol/bc/types"
10 )
11
12 var (
13         ErrFoundHeaderByHash   = errors.New("can't find header by hash")
14         ErrFoundHeaderByHeight = errors.New("can't find header by height")
15 )
16
17 type mempool interface {
18         AddTx(tx *types.Tx)
19 }
20
21 type Chain struct {
22         bestBlockHeader *types.BlockHeader
23         heightMap       map[uint64]*types.Block
24         blockMap        map[bc.Hash]*types.Block
25         prevOrphans     map[bc.Hash]*types.Block
26         mempool         mempool
27 }
28
29 func NewChain(mempool *Mempool) *Chain {
30         return &Chain{
31                 bestBlockHeader: &types.BlockHeader{},
32                 heightMap:       map[uint64]*types.Block{},
33                 blockMap:        map[bc.Hash]*types.Block{},
34                 prevOrphans:     make(map[bc.Hash]*types.Block),
35                 mempool:         mempool,
36         }
37 }
38
39 func (c *Chain) BestBlockHeader() *types.BlockHeader {
40         return c.bestBlockHeader
41 }
42
43 func (c *Chain) BestBlockHeight() uint64 {
44         return c.bestBlockHeader.Height
45 }
46
47 func (c *Chain) LastIrreversibleHeader() *types.BlockHeader {
48         return c.bestBlockHeader
49 }
50
51 func (c *Chain) CalcNextSeed(hash *bc.Hash) (*bc.Hash, error) {
52         return &bc.Hash{V0: hash.V1, V1: hash.V2, V2: hash.V3, V3: hash.V0}, nil
53 }
54
55 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*types.Block, error) {
56         block, ok := c.blockMap[*hash]
57         if !ok {
58                 return nil, errors.New("can't find block")
59         }
60         return block, nil
61 }
62
63 func (c *Chain) GetBlockByHeight(height uint64) (*types.Block, error) {
64         block, ok := c.heightMap[height]
65         if !ok {
66                 return nil, errors.New("can't find block")
67         }
68         return block, nil
69 }
70
71 func (c *Chain) GetHeaderByHash(hash *bc.Hash) (*types.BlockHeader, error) {
72         block, ok := c.blockMap[*hash]
73         if !ok {
74                 return nil, ErrFoundHeaderByHash
75         }
76         return &block.BlockHeader, nil
77 }
78
79 func (c *Chain) GetHeaderByHeight(height uint64) (*types.BlockHeader, error) {
80         block, ok := c.heightMap[height]
81         if !ok {
82                 return nil, ErrFoundHeaderByHeight
83         }
84         return &block.BlockHeader, nil
85 }
86
87 func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
88         block, err := c.GetBlockByHash(hash)
89         if err != nil {
90                 return nil, errors.New("can't find block by hash")
91         }
92         txCount := len(block.Transactions)
93         var statuses []*bc.TxVerifyResult
94         rand.Seed(int64(block.Height))
95         for i := 0; i < txCount; i++ {
96                 status := &bc.TxVerifyResult{}
97                 if fail := rand.Intn(2); fail == 0 {
98                         status.StatusFail = true
99                 } else {
100                         status.StatusFail = false
101                 }
102                 statuses = append(statuses, status)
103         }
104         txStatus := &bc.TransactionStatus{VerifyStatus: statuses}
105         return txStatus, nil
106 }
107
108 func (c *Chain) InMainChain(hash bc.Hash) bool {
109         block, ok := c.blockMap[hash]
110         if !ok {
111                 return false
112         }
113         return c.heightMap[block.Height] == block
114 }
115
116 func (c *Chain) ProcessBlock(block *types.Block) (bool, error) {
117         if block.TransactionsMerkleRoot == bc.NewHash([32]byte{0x1}) {
118                 return false, protocol.ErrBadStateRoot
119         }
120
121         if c.bestBlockHeader.Hash() == block.PreviousBlockHash {
122                 c.heightMap[block.Height] = block
123                 c.blockMap[block.Hash()] = block
124                 c.bestBlockHeader = &block.BlockHeader
125                 return false, nil
126         }
127
128         if _, ok := c.blockMap[block.PreviousBlockHash]; !ok {
129                 c.prevOrphans[block.PreviousBlockHash] = block
130                 return true, nil
131         }
132
133         c.blockMap[block.Hash()] = block
134         for c.prevOrphans[block.Hash()] != nil {
135                 block = c.prevOrphans[block.Hash()]
136                 c.blockMap[block.Hash()] = block
137         }
138
139         if block.Height < c.bestBlockHeader.Height {
140                 return false, nil
141         }
142
143         c.bestBlockHeader = &block.BlockHeader
144         for !c.InMainChain(block.Hash()) {
145                 c.heightMap[block.Height] = block
146                 block = c.blockMap[block.PreviousBlockHash]
147         }
148         return false, nil
149 }
150
151 // TODO:
152 func (c *Chain) ProcessBlockSignature(signature, pubkey []byte, blockHash *bc.Hash) error {
153         return nil
154 }
155
156 func (c *Chain) SetBestBlockHeader(header *types.BlockHeader) {
157         c.bestBlockHeader = header
158 }
159
160 func (c *Chain) SetBlockByHeight(height uint64, block *types.Block) {
161         c.heightMap[height] = block
162         c.blockMap[block.Hash()] = block
163 }
164
165 func (c *Chain) ValidateTx(tx *types.Tx) (bool, error) {
166         c.mempool.AddTx(tx)
167         return false, nil
168 }