4 "github.com/bytom/errors"
5 "github.com/bytom/protocol/bc"
6 "github.com/bytom/protocol/bc/legacy"
7 "github.com/bytom/protocol/state"
8 "github.com/bytom/protocol/validation"
12 // ErrBadBlock is returned when a block is invalid.
13 ErrBadBlock = errors.New("invalid block")
15 // ErrStaleState is returned when the Chain does not have a current
17 ErrStaleState = errors.New("stale blockchain state")
19 // ErrBadStateRoot is returned when the computed assets merkle root
20 // disagrees with the one declared in a block header.
21 ErrBadStateRoot = errors.New("invalid state merkle root")
24 func (c *Chain) BlockExist(hash *bc.Hash) bool {
25 return c.orphanManage.BlockExist(hash) || c.store.BlockExist(hash)
28 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*legacy.Block, error) {
29 return c.store.GetBlock(hash)
32 func (c *Chain) GetBlockByHeight(height uint64) (*legacy.Block, error) {
34 hash, ok := c.state.mainChain[height]
35 c.state.cond.L.Unlock()
37 return nil, errors.New("can't find block in given hight")
39 return c.GetBlockByHash(hash)
42 // ValidateBlock validates an incoming block in advance of applying it
43 // to a snapshot (with ApplyValidBlock) and committing it to the
44 // blockchain (with CommitAppliedBlock).
45 func (c *Chain) ValidateBlock(block, prev *legacy.Block) error {
46 blockEnts := legacy.MapBlock(block)
47 prevEnts := legacy.MapBlock(prev)
48 if err := validation.ValidateBlock(blockEnts, prevEnts); err != nil {
49 return errors.Sub(ErrBadBlock, err)
54 // ApplyValidBlock creates an updated snapshot without validating the
56 func (c *Chain) ConnectBlock(block *legacy.Block) error {
57 newSnapshot := state.Copy(c.state.snapshot)
58 if err := newSnapshot.ApplyBlock(legacy.MapBlock(block)); err != nil {
62 blockHash := block.Hash()
63 if err := c.setState(block, newSnapshot, map[uint64]*bc.Hash{block.Height: &blockHash}); err != nil {
67 for _, tx := range block.Transactions {
68 c.txPool.RemoveTransaction(&tx.Tx.ID)
73 func (c *Chain) getReorganizeBlocks(block *legacy.Block) ([]*legacy.Block, []*legacy.Block) {
74 attachBlocks := []*legacy.Block{}
75 detachBlocks := []*legacy.Block{}
78 for !c.InMainchain(ancestor) {
79 attachBlocks = append([]*legacy.Block{ancestor}, attachBlocks...)
80 ancestor, _ = c.GetBlockByHash(&ancestor.PreviousBlockHash)
83 for d := c.state.block; d.Hash() != ancestor.Hash(); d, _ = c.GetBlockByHash(&d.PreviousBlockHash) {
84 detachBlocks = append(detachBlocks, d)
87 return attachBlocks, detachBlocks
90 func (c *Chain) reorganizeChain(block *legacy.Block) error {
91 attachBlocks, detachBlocks := c.getReorganizeBlocks(block)
92 newSnapshot := state.Copy(c.state.snapshot)
93 chainChanges := map[uint64]*bc.Hash{}
95 for _, d := range detachBlocks {
96 if err := newSnapshot.DetachBlock(legacy.MapBlock(d)); err != nil {
101 for _, a := range attachBlocks {
102 if err := newSnapshot.ApplyBlock(legacy.MapBlock(a)); err != nil {
106 chainChanges[a.Height] = &aHash
109 return c.setState(block, newSnapshot, chainChanges)
112 func (c *Chain) SaveBlock(block *legacy.Block) error {
113 preBlock, _ := c.GetBlockByHash(&block.PreviousBlockHash)
114 if err := c.ValidateBlock(block, preBlock); err != nil {
117 if err := c.store.SaveBlock(block); err != nil {
121 preorphans, ok := c.orphanManage.preOrphans[block.Hash()]
125 for _, preorphan := range preorphans {
126 orphanBlock, ok := c.orphanManage.Get(preorphan)
130 c.SaveBlock(orphanBlock)
131 c.orphanManage.Delete(preorphan)
136 func (c *Chain) ProcessBlock(block *legacy.Block) (bool, error) {
137 if blockHash := block.Hash(); c.BlockExist(&blockHash) {
140 if !c.BlockExist(&block.PreviousBlockHash) {
141 c.orphanManage.Add(block)
144 if err := c.SaveBlock(block); err != nil {
148 c.state.cond.L.Lock()
149 if c.state.block.Hash() == block.PreviousBlockHash {
150 defer c.state.cond.L.Unlock()
151 return false, c.ConnectBlock(block)
154 if block.Height > c.state.height && block.Bits >= c.state.block.Bits {
155 defer c.state.cond.L.Unlock()
156 return false, c.reorganizeChain(block)
158 c.state.cond.L.Unlock()