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 bestBlockHeader: &types.BlockHeader{},
32 heightMap: map[uint64]*types.Block{},
33 blockMap: map[bc.Hash]*types.Block{},
34 prevOrphans: make(map[bc.Hash]*types.Block),
39 func (c *Chain) BestBlockHeader() *types.BlockHeader {
40 return c.bestBlockHeader
43 func (c *Chain) BestBlockHeight() uint64 {
44 return c.bestBlockHeader.Height
47 func (c *Chain) LastIrreversibleHeader() *types.BlockHeader {
48 return c.bestBlockHeader
51 func (c *Chain) CalcNextSeed(hash *bc.Hash) (*bc.Hash, error) {
52 return &bc.Hash{V0: hash.V1, V1: hash.V2, V2: hash.V3, V3: hash.V0}, nil
55 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*types.Block, error) {
56 block, ok := c.blockMap[*hash]
58 return nil, errors.New("can't find block")
63 func (c *Chain) GetBlockByHeight(height uint64) (*types.Block, error) {
64 block, ok := c.heightMap[height]
66 return nil, errors.New("can't find block")
71 func (c *Chain) GetHeaderByHash(hash *bc.Hash) (*types.BlockHeader, error) {
72 block, ok := c.blockMap[*hash]
74 return nil, ErrFoundHeaderByHash
76 return &block.BlockHeader, nil
79 func (c *Chain) GetHeaderByHeight(height uint64) (*types.BlockHeader, error) {
80 block, ok := c.heightMap[height]
82 return nil, ErrFoundHeaderByHeight
84 return &block.BlockHeader, nil
87 func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
88 block, err := c.GetBlockByHash(hash)
90 return nil, errors.New("can't find block by hash")
92 txCount := len(block.Transactions)
93 var statuses []*bc.TxVerifyResult
94 rand.Seed(int64(block.Height))
95 for i := 0; i < txCount; i++ {
96 status := &bc.TxVerifyResult{}
97 if fail := rand.Intn(2); fail == 0 {
98 status.StatusFail = true
100 status.StatusFail = false
102 statuses = append(statuses, status)
104 txStatus := &bc.TransactionStatus{VerifyStatus: statuses}
108 func (c *Chain) InMainChain(hash bc.Hash) bool {
109 block, ok := c.blockMap[hash]
113 return c.heightMap[block.Height] == block
116 func (c *Chain) ProcessBlock(block *types.Block) (bool, error) {
117 if block.TransactionsMerkleRoot == bc.NewHash([32]byte{0x1}) {
118 return false, protocol.ErrBadStateRoot
121 if c.bestBlockHeader.Hash() == block.PreviousBlockHash {
122 c.heightMap[block.Height] = block
123 c.blockMap[block.Hash()] = block
124 c.bestBlockHeader = &block.BlockHeader
128 if _, ok := c.blockMap[block.PreviousBlockHash]; !ok {
129 c.prevOrphans[block.PreviousBlockHash] = block
133 c.blockMap[block.Hash()] = block
134 for c.prevOrphans[block.Hash()] != nil {
135 block = c.prevOrphans[block.Hash()]
136 c.blockMap[block.Hash()] = block
139 if block.Height < c.bestBlockHeader.Height {
143 c.bestBlockHeader = &block.BlockHeader
144 for !c.InMainChain(block.Hash()) {
145 c.heightMap[block.Height] = block
146 block = c.blockMap[block.PreviousBlockHash]
152 func (c *Chain) ProcessBlockSignature(signature, pubkey []byte, blockHash *bc.Hash) error {
156 func (c *Chain) SetBestBlockHeader(header *types.BlockHeader) {
157 c.bestBlockHeader = header
160 func (c *Chain) SetBlockByHeight(height uint64, block *types.Block) {
161 c.heightMap[height] = block
162 c.blockMap[block.Hash()] = block
165 func (c *Chain) ValidateTx(tx *types.Tx) (bool, error) {