7 "github.com/vapor/protocol"
8 "github.com/vapor/protocol/bc"
9 "github.com/vapor/protocol/bc/types"
13 ErrFoundHeaderByHash = errors.New("can't find header by hash")
14 ErrFoundHeaderByHeight = errors.New("can't find header by height")
17 type mempool interface {
22 bestBlockHeader *types.BlockHeader
23 heightMap map[uint64]*types.Block
24 blockMap map[bc.Hash]*types.Block
25 prevOrphans map[bc.Hash]*types.Block
29 func NewChain(mempool *Mempool) *Chain {
31 heightMap: map[uint64]*types.Block{},
32 blockMap: map[bc.Hash]*types.Block{},
33 prevOrphans: make(map[bc.Hash]*types.Block),
38 func (c *Chain) BestBlockHeader() *types.BlockHeader {
39 return c.bestBlockHeader
42 func (c *Chain) BestBlockHeight() uint64 {
43 return c.bestBlockHeader.Height
46 func (c *Chain) LastIrreversibleHeader() *types.BlockHeader {
47 return c.bestBlockHeader
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
54 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*types.Block, error) {
55 block, ok := c.blockMap[*hash]
57 return nil, errors.New("can't find block")
62 func (c *Chain) GetBlockByHeight(height uint64) (*types.Block, error) {
63 block, ok := c.heightMap[height]
65 return nil, errors.New("can't find block")
70 func (c *Chain) GetHeaderByHash(hash *bc.Hash) (*types.BlockHeader, error) {
71 block, ok := c.blockMap[*hash]
73 return nil, ErrFoundHeaderByHash
75 return &block.BlockHeader, nil
78 func (c *Chain) GetHeaderByHeight(height uint64) (*types.BlockHeader, error) {
79 block, ok := c.heightMap[height]
81 return nil, ErrFoundHeaderByHeight
83 return &block.BlockHeader, nil
86 func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
87 block, err := c.GetBlockByHash(hash)
89 return nil, errors.New("can't find block by hash")
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
99 status.StatusFail = false
101 statuses = append(statuses, status)
103 txStatus := &bc.TransactionStatus{VerifyStatus: statuses}
107 func (c *Chain) InMainChain(hash bc.Hash) bool {
108 block, ok := c.blockMap[hash]
112 return c.heightMap[block.Height] == block
115 func (c *Chain) ProcessBlock(block *types.Block) (bool, error) {
116 if block.TransactionsMerkleRoot == bc.NewHash([32]byte{0x1}) {
117 return false, protocol.ErrBadStateRoot
120 if c.bestBlockHeader.Hash() == block.PreviousBlockHash {
121 c.heightMap[block.Height] = block
122 c.blockMap[block.Hash()] = block
123 c.bestBlockHeader = &block.BlockHeader
127 if _, ok := c.blockMap[block.PreviousBlockHash]; !ok {
128 c.prevOrphans[block.PreviousBlockHash] = block
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
138 if block.Height < c.bestBlockHeader.Height {
142 c.bestBlockHeader = &block.BlockHeader
143 for !c.InMainChain(block.Hash()) {
144 c.heightMap[block.Height] = block
145 block = c.blockMap[block.PreviousBlockHash]
150 func (c *Chain) SetBestBlockHeader(header *types.BlockHeader) {
151 c.bestBlockHeader = header
154 func (c *Chain) SetBlockByHeight(height uint64, block *types.Block) {
155 c.heightMap[height] = block
156 c.blockMap[block.Hash()] = block
159 func (c *Chain) ValidateTx(tx *types.Tx) (bool, error) {