7 "github.com/vapor/protocol/bc"
8 "github.com/vapor/protocol/bc/types"
12 bestBlockHeader *types.BlockHeader
13 heightMap map[uint64]*types.Block
14 blockMap map[bc.Hash]*types.Block
16 prevOrphans map[bc.Hash]*types.Block
19 func NewChain() *Chain {
21 heightMap: map[uint64]*types.Block{},
22 blockMap: map[bc.Hash]*types.Block{},
23 prevOrphans: make(map[bc.Hash]*types.Block),
27 func (c *Chain) BestBlockHeader() *types.BlockHeader {
28 return c.bestBlockHeader
31 func (c *Chain) BestBlockHeight() uint64 {
32 return c.bestBlockHeader.Height
35 func (c *Chain) CalcNextSeed(hash *bc.Hash) (*bc.Hash, error) {
36 return &bc.Hash{V0: hash.V1, V1: hash.V2, V2: hash.V3, V3: hash.V0}, nil
39 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*types.Block, error) {
40 block, ok := c.blockMap[*hash]
42 return nil, errors.New("can't find block")
47 func (c *Chain) GetBlockByHeight(height uint64) (*types.Block, error) {
48 block, ok := c.heightMap[height]
50 return nil, errors.New("can't find block")
55 func (c *Chain) GetHeaderByHash(hash *bc.Hash) (*types.BlockHeader, error) {
56 block, ok := c.blockMap[*hash]
58 return nil, errors.New("can't find block")
60 return &block.BlockHeader, nil
63 func (c *Chain) GetHeaderByHeight(height uint64) (*types.BlockHeader, error) {
64 block, ok := c.heightMap[height]
66 return nil, errors.New("can't find block")
68 return &block.BlockHeader, nil
71 func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
72 block, err := c.GetBlockByHash(hash)
74 return nil, errors.New("can't find block by hash")
76 txCount := len(block.Transactions)
77 var statuses []*bc.TxVerifyResult
78 rand.Seed(int64(block.Height))
79 for i := 0; i < txCount; i++ {
80 status := &bc.TxVerifyResult{}
81 if fail := rand.Intn(2); fail == 0 {
82 status.StatusFail = true
84 status.StatusFail = false
86 statuses = append(statuses, status)
88 txStatus := &bc.TransactionStatus{VerifyStatus: statuses}
92 func (c *Chain) InMainChain(hash bc.Hash) bool {
93 block, ok := c.blockMap[hash]
97 return c.heightMap[block.Height] == block
100 func (c *Chain) ProcessBlock(block *types.Block) (bool, error) {
101 if c.bestBlockHeader.Hash() == block.PreviousBlockHash {
102 c.heightMap[block.Height] = block
103 c.blockMap[block.Hash()] = block
104 c.bestBlockHeader = &block.BlockHeader
108 if _, ok := c.blockMap[block.PreviousBlockHash]; !ok {
109 c.prevOrphans[block.PreviousBlockHash] = block
113 c.blockMap[block.Hash()] = block
114 for c.prevOrphans[block.Hash()] != nil {
115 block = c.prevOrphans[block.Hash()]
116 c.blockMap[block.Hash()] = block
119 if block.Height < c.bestBlockHeader.Height {
123 c.bestBlockHeader = &block.BlockHeader
124 for !c.InMainChain(block.Hash()) {
125 c.heightMap[block.Height] = block
126 block = c.blockMap[block.PreviousBlockHash]
131 func (c *Chain) SetBestBlockHeader(header *types.BlockHeader) {
132 c.bestBlockHeader = header
135 func (c *Chain) SetBlockByHeight(height uint64, block *types.Block) {
136 c.heightMap[height] = block
137 c.blockMap[block.Hash()] = block
140 func (c *Chain) ValidateTx(*types.Tx) (bool, error) {