OSDN Git Service

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