6 log "github.com/sirupsen/logrus"
8 "github.com/bytom/bytom/config"
9 "github.com/bytom/bytom/event"
10 "github.com/bytom/bytom/protocol/bc"
11 "github.com/bytom/bytom/protocol/bc/types"
12 "github.com/bytom/bytom/protocol/state"
15 const maxProcessBlockChSize = 1024
17 // Chain provides functions for working with the Bytom block chain.
19 index *state.BlockIndex
20 orphanManage *OrphanManage
23 processBlockCh chan *processBlockMsg
24 rollbackBlockCh chan bc.Hash
25 casper CasperConsensus
26 eventDispatcher *event.Dispatcher
29 bestNode *state.BlockNode
32 // NewChain returns a new Chain using store as the underlying storage.
33 func NewChain(store Store, txPool *TxPool) (*Chain, error) {
34 return NewChainWithOrphanManage(store, txPool, NewOrphanManage())
37 func NewChainWithOrphanManage(store Store, txPool *TxPool, manage *OrphanManage) (*Chain, error) {
42 processBlockCh: make(chan *processBlockMsg, maxProcessBlockChSize),
44 c.cond.L = new(sync.Mutex)
46 storeStatus := store.GetStoreStatus()
47 if storeStatus == nil {
48 if err := c.initChainStatus(); err != nil {
51 storeStatus = store.GetStoreStatus()
55 if c.index, err = store.LoadBlockIndex(storeStatus.Height); err != nil {
59 c.bestNode = c.index.GetNode(storeStatus.Hash)
60 c.index.SetMainChain(c.bestNode)
65 func (c *Chain) initChainStatus() error {
66 genesisBlock := config.GenesisBlock()
67 if err := c.store.SaveBlock(genesisBlock); err != nil {
71 utxoView := state.NewUtxoViewpoint()
72 bcBlock := types.MapBlock(genesisBlock)
73 if err := utxoView.ApplyBlock(bcBlock); err != nil {
77 node, err := state.NewBlockNode(&genesisBlock.BlockHeader, nil)
82 contractView := state.NewContractViewpoint()
83 return c.store.SaveChainStatus(node, utxoView, contractView)
86 // BestBlockHeight returns the last irreversible block header of the blockchain
87 func (c *Chain) LastIrreversibleHeader() *types.BlockHeader {
88 _, hash := c.casper.LastFinalized()
89 node := c.index.GetNode(&hash)
90 return node.BlockHeader()
93 // ProcessBlockVerification process block verification
94 func (c *Chain) ProcessBlockVerification(v *Verification) error {
95 return c.casper.AuthVerification(v)
98 // BestBlockHeight returns the current height of the blockchain.
99 func (c *Chain) BestBlockHeight() uint64 {
101 defer c.cond.L.Unlock()
102 return c.bestNode.Height
105 // BestBlockHash return the hash of the chain tail block
106 func (c *Chain) BestBlockHash() *bc.Hash {
108 defer c.cond.L.Unlock()
109 return &c.bestNode.Hash
112 // BestBlockHeader returns the chain tail block
113 func (c *Chain) BestBlockHeader() *types.BlockHeader {
114 node := c.index.BestNode()
115 return node.BlockHeader()
118 // InMainChain checks wheather a block is in the main chain
119 func (c *Chain) InMainChain(hash bc.Hash) bool {
120 return c.index.InMainchain(hash)
123 func (c *Chain) GetBlockIndex() *state.BlockIndex {
127 func (c *Chain) SignBlockHeader(blockHeader *types.BlockHeader) {
129 defer c.cond.L.Unlock()
130 xprv := config.CommonConfig.PrivateKey()
131 signature := xprv.Sign(blockHeader.Hash().Bytes())
132 blockHeader.Set(signature)
135 // This function must be called with mu lock in above level
136 func (c *Chain) setState(node *state.BlockNode, view *state.UtxoViewpoint, contractView *state.ContractViewpoint) error {
137 if err := c.store.SaveChainStatus(node, view, contractView); err != nil {
142 defer c.cond.L.Unlock()
144 c.index.SetMainChain(node)
147 log.WithFields(log.Fields{"module": logModule, "height": c.bestNode.Height, "hash": c.bestNode.Hash.String()}).Debug("chain best status has been update")
152 // BlockWaiter returns a channel that waits for the block at the given height.
153 func (c *Chain) BlockWaiter(height uint64) <-chan struct{} {
154 ch := make(chan struct{}, 1)
157 defer c.cond.L.Unlock()
158 for c.bestNode.Height < height {
167 // GetTxPool return chain txpool.
168 func (c *Chain) GetTxPool() *TxPool {