7 "github.com/vapor/protocol/bc"
8 "github.com/vapor/protocol/bc/types"
11 type mempool interface {
16 bestBlockHeader *types.BlockHeader
17 heightMap map[uint64]*types.Block
18 blockMap map[bc.Hash]*types.Block
19 prevOrphans map[bc.Hash]*types.Block
23 func NewChain(mempool *Mempool) *Chain {
25 heightMap: map[uint64]*types.Block{},
26 blockMap: map[bc.Hash]*types.Block{},
27 prevOrphans: make(map[bc.Hash]*types.Block),
32 func (c *Chain) BestBlockHeader() *types.BlockHeader {
33 return c.bestBlockHeader
36 func (c *Chain) BestBlockHeight() uint64 {
37 return c.bestBlockHeader.Height
40 func (c *Chain) CalcNextSeed(hash *bc.Hash) (*bc.Hash, error) {
41 return &bc.Hash{V0: hash.V1, V1: hash.V2, V2: hash.V3, V3: hash.V0}, nil
44 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*types.Block, error) {
45 block, ok := c.blockMap[*hash]
47 return nil, errors.New("can't find block")
52 func (c *Chain) GetBlockByHeight(height uint64) (*types.Block, error) {
53 block, ok := c.heightMap[height]
55 return nil, errors.New("can't find block")
60 func (c *Chain) GetHeaderByHash(hash *bc.Hash) (*types.BlockHeader, error) {
61 block, ok := c.blockMap[*hash]
63 return nil, errors.New("can't find block")
65 return &block.BlockHeader, nil
68 func (c *Chain) GetHeaderByHeight(height uint64) (*types.BlockHeader, error) {
69 block, ok := c.heightMap[height]
71 return nil, errors.New("can't find block")
73 return &block.BlockHeader, nil
76 func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
77 block, err := c.GetBlockByHash(hash)
79 return nil, errors.New("can't find block by hash")
81 txCount := len(block.Transactions)
82 var statuses []*bc.TxVerifyResult
83 rand.Seed(int64(block.Height))
84 for i := 0; i < txCount; i++ {
85 status := &bc.TxVerifyResult{}
86 if fail := rand.Intn(2); fail == 0 {
87 status.StatusFail = true
89 status.StatusFail = false
91 statuses = append(statuses, status)
93 txStatus := &bc.TransactionStatus{VerifyStatus: statuses}
97 func (c *Chain) InMainChain(hash bc.Hash) bool {
98 block, ok := c.blockMap[hash]
102 return c.heightMap[block.Height] == block
105 func (c *Chain) ProcessBlock(block *types.Block) (bool, error) {
106 if c.bestBlockHeader.Hash() == block.PreviousBlockHash {
107 c.heightMap[block.Height] = block
108 c.blockMap[block.Hash()] = block
109 c.bestBlockHeader = &block.BlockHeader
113 if _, ok := c.blockMap[block.PreviousBlockHash]; !ok {
114 c.prevOrphans[block.PreviousBlockHash] = block
118 c.blockMap[block.Hash()] = block
119 for c.prevOrphans[block.Hash()] != nil {
120 block = c.prevOrphans[block.Hash()]
121 c.blockMap[block.Hash()] = block
124 if block.Height < c.bestBlockHeader.Height {
128 c.bestBlockHeader = &block.BlockHeader
129 for !c.InMainChain(block.Hash()) {
130 c.heightMap[block.Height] = block
131 block = c.blockMap[block.PreviousBlockHash]
136 func (c *Chain) SetBestBlockHeader(header *types.BlockHeader) {
137 c.bestBlockHeader = header
140 func (c *Chain) SetBlockByHeight(height uint64, block *types.Block) {
141 c.heightMap[height] = block
142 c.blockMap[block.Hash()] = block
145 func (c *Chain) ValidateTx(tx *types.Tx) (bool, error) {