OSDN Git Service

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