X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=protocol%2Fprotocol.go;h=39ef664ff99d342f23fa3cd181d8101e825ecdbd;hp=ba60e08d33850d2d4fb71a8b78fe0b666ee78609;hb=42c5ab23c13e7f43d0055221ec38752555bd987e;hpb=369882c62ed2ccfe13f9d0ff918076a52ed7b91b diff --git a/protocol/protocol.go b/protocol/protocol.go index ba60e08d..39ef664f 100644 --- a/protocol/protocol.go +++ b/protocol/protocol.go @@ -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,25 +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 - 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, engine engine.Engine) (*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), - engine: engine, + orphanManage: NewOrphanManage(), + txPool: txPool, + store: store, + signatureCache: common.NewCache(maxSignatureCacheSize), + eventDispatcher: eventDispatcher, + processBlockCh: make(chan *processBlockMsg, maxProcessBlockChSize), } c.cond.L = new(sync.Mutex) @@ -48,20 +51,19 @@ func NewChain(store Store, txPool *TxPool, engine engine.Engine) (*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) SetConsensusEngine(engine engine.Engine) { - c.engine = engine -} - func (c *Chain) initChainStatus() error { genesisBlock := config.GenesisBlock() txStatus := bc.NewTransactionStatus() @@ -81,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 } @@ -154,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{}{}