OSDN Git Service

get BlockNode from database (#188)
[bytom/vapor.git] / protocol / protocol.go
index ff61e18..39ef664 100644 (file)
@@ -5,9 +5,9 @@ import (
 
        log "github.com/sirupsen/logrus"
 
+       "github.com/vapor/common"
        "github.com/vapor/config"
-       engine "github.com/vapor/consensus/consensus"
-       "github.com/vapor/errors"
+       "github.com/vapor/event"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
        "github.com/vapor/protocol/state"
@@ -17,26 +17,28 @@ const maxProcessBlockChSize = 1024
 
 // Chain provides functions for working with the Bytom block chain.
 type Chain struct {
-       index          *state.BlockIndex
        orphanManage   *OrphanManage
        txPool         *TxPool
        store          Store
        processBlockCh chan *processBlockMsg
 
-       cond       sync.Cond
-       bestNode   *state.BlockNode
-       Authoritys map[string]string
-       position   uint64
-       engine     engine.Engine
+       signatureCache  *common.Cache
+       eventDispatcher *event.Dispatcher
+
+       cond               sync.Cond
+       bestBlockHeader    *types.BlockHeader
+       bestIrrBlockHeader *types.BlockHeader
 }
 
 // NewChain returns a new Chain using store as the underlying storage.
-func NewChain(store Store, txPool *TxPool) (*Chain, error) {
+func NewChain(store Store, txPool *TxPool, eventDispatcher *event.Dispatcher) (*Chain, error) {
        c := &Chain{
-               orphanManage:   NewOrphanManage(),
-               txPool:         txPool,
-               store:          store,
-               processBlockCh: make(chan *processBlockMsg, maxProcessBlockChSize),
+               orphanManage:    NewOrphanManage(),
+               txPool:          txPool,
+               store:           store,
+               signatureCache:  common.NewCache(maxSignatureCacheSize),
+               eventDispatcher: eventDispatcher,
+               processBlockCh:  make(chan *processBlockMsg, maxProcessBlockChSize),
        }
        c.cond.L = new(sync.Mutex)
 
@@ -49,28 +51,19 @@ func NewChain(store Store, txPool *TxPool) (*Chain, error) {
        }
 
        var err error
-       if c.index, err = store.LoadBlockIndex(storeStatus.Height); err != nil {
+       c.bestBlockHeader, err = c.store.GetBlockHeader(storeStatus.Hash)
+       if err != nil {
                return nil, err
        }
 
-       c.bestNode = c.index.GetNode(storeStatus.Hash)
-       c.index.SetMainChain(c.bestNode)
+       c.bestIrrBlockHeader, err = c.store.GetBlockHeader(storeStatus.IrreversibleHash)
+       if err != nil {
+               return nil, err
+       }
        go c.blockProcesser()
        return c, nil
 }
 
-func (c *Chain) SetAuthoritys(authoritys map[string]string) {
-       c.Authoritys = authoritys
-}
-
-func (c *Chain) SetPosition(position uint64) {
-       c.position = position
-}
-
-func (c *Chain) SetConsensusEngine(engine engine.Engine) {
-       c.engine = engine
-}
-
 func (c *Chain) initChainStatus() error {
        genesisBlock := config.GenesisBlock()
        txStatus := bc.NewTransactionStatus()
@@ -90,69 +83,72 @@ func (c *Chain) initChainStatus() error {
                return err
        }
 
-       node, err := state.NewBlockNode(&genesisBlock.BlockHeader, nil)
-       if err != nil {
-               return err
-       }
-       return c.store.SaveChainStatus(node, utxoView)
+       voteResults := []*state.VoteResult{&state.VoteResult{
+               Seq:         0,
+               NumOfVote:   map[string]uint64{},
+               BlockHash:   genesisBlock.Hash(),
+               BlockHeight: 0,
+       }}
+
+       genesisBlockHeader := &genesisBlock.BlockHeader
+       return c.store.SaveChainStatus(genesisBlockHeader, genesisBlockHeader, []*types.BlockHeader{genesisBlockHeader}, utxoView, voteResults)
 }
 
 // BestBlockHeight returns the current height of the blockchain.
 func (c *Chain) BestBlockHeight() uint64 {
        c.cond.L.Lock()
        defer c.cond.L.Unlock()
-       return c.bestNode.Height
+       return c.bestBlockHeader.Height
 }
 
 // BestBlockHash return the hash of the chain tail block
 func (c *Chain) BestBlockHash() *bc.Hash {
        c.cond.L.Lock()
        defer c.cond.L.Unlock()
-       return &c.bestNode.Hash
+       bestHash := c.bestBlockHeader.Hash()
+       return &bestHash
 }
 
-// BestBlockHeader returns the chain tail block
+// BestIrreversibleHeader returns the chain best irreversible block header
+func (c *Chain) BestIrreversibleHeader() *types.BlockHeader {
+       c.cond.L.Lock()
+       defer c.cond.L.Unlock()
+       return c.bestIrrBlockHeader
+}
+
+// BestBlockHeader returns the chain best block header
 func (c *Chain) BestBlockHeader() *types.BlockHeader {
-       node := c.index.BestNode()
-       return node.BlockHeader()
+       c.cond.L.Lock()
+       defer c.cond.L.Unlock()
+       return c.bestBlockHeader
 }
 
 // InMainChain checks wheather a block is in the main chain
 func (c *Chain) InMainChain(hash bc.Hash) bool {
-       return c.index.InMainchain(hash)
-}
-
-// CalcNextSeed return the seed for the given block
-func (c *Chain) CalcNextSeed(preBlock *bc.Hash) (*bc.Hash, error) {
-       node := c.index.GetNode(preBlock)
-       if node == nil {
-               return nil, errors.New("can't find preblock in the blockindex")
+       blockHeader, err := c.store.GetBlockHeader(&hash)
+       if err != nil {
+               return false
        }
-       return node.CalcNextSeed(), nil
-}
 
-// CalcNextBits return the seed for the given block
-func (c *Chain) CalcNextBits(preBlock *bc.Hash) (uint64, error) {
-       node := c.index.GetNode(preBlock)
-       if node == nil {
-               return 0, errors.New("can't find preblock in the blockindex")
+       blockHash, err := c.store.GetMainChainHash(blockHeader.Height)
+       if err != nil {
+               log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height}).Debug("not contain block hash in main chain for specified height")
+               return false
        }
-       return node.CalcNextBits(), nil
+       return *blockHash == hash
 }
 
 // This function must be called with mu lock in above level
-func (c *Chain) setState(node *state.BlockNode, view *state.UtxoViewpoint) error {
-       if err := c.store.SaveChainStatus(node, view); err != nil {
+func (c *Chain) setState(blockHeader, irrBlockHeader *types.BlockHeader, mainBlockHeaders []*types.BlockHeader, view *state.UtxoViewpoint, voteResults []*state.VoteResult) error {
+       if err := c.store.SaveChainStatus(blockHeader, irrBlockHeader, mainBlockHeaders, view, voteResults); err != nil {
                return err
        }
 
-       c.cond.L.Lock()
-       defer c.cond.L.Unlock()
-
-       c.index.SetMainChain(node)
-       c.bestNode = node
+       c.bestBlockHeader = blockHeader
+       c.bestIrrBlockHeader = irrBlockHeader
 
-       log.WithFields(log.Fields{"height": c.bestNode.Height, "hash": c.bestNode.Hash.String()}).Debug("chain best status has been update")
+       blockHash := blockHeader.Hash()
+       log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("chain best status has been update")
        c.cond.Broadcast()
        return nil
 }
@@ -163,7 +159,7 @@ func (c *Chain) BlockWaiter(height uint64) <-chan struct{} {
        go func() {
                c.cond.L.Lock()
                defer c.cond.L.Unlock()
-               for c.bestNode.Height < height {
+               for c.bestBlockHeader.Height < height {
                        c.cond.Wait()
                }
                ch <- struct{}{}