X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=protocol%2Fprotocol.go;h=d7ea94484e8986833e1f2143f3b95e2fcd524dac;hb=refs%2Fheads%2Ffixconsensusreward;hp=153312ca6d7700b830d2645a83b26bbb537130ea;hpb=1005d5aeca37334f61be9ffb3631137eb7d6088d;p=bytom%2Fvapor.git diff --git a/protocol/protocol.go b/protocol/protocol.go index 153312ca..d7ea9448 100644 --- a/protocol/protocol.go +++ b/protocol/protocol.go @@ -13,7 +13,10 @@ import ( "github.com/vapor/protocol/state" ) -const maxProcessBlockChSize = 1024 +const ( + maxProcessBlockChSize = 1024 + maxKnownTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS) +) // Chain provides functions for working with the Bytom block chain. type Chain struct { @@ -26,12 +29,15 @@ type Chain struct { eventDispatcher *event.Dispatcher cond sync.Cond - bestBlockHeader *types.BlockHeader - bestIrrBlockHeader *types.BlockHeader + bestBlockHeader *types.BlockHeader // the last block on current main chain + lastIrrBlockHeader *types.BlockHeader // the last irreversible block + + knownTxs *common.OrderedSet } // NewChain returns a new Chain using store as the underlying storage. func NewChain(store Store, txPool *TxPool, eventDispatcher *event.Dispatcher) (*Chain, error) { + knownTxs, _ := common.NewOrderedSet(maxKnownTxs) c := &Chain{ orphanManage: NewOrphanManage(), txPool: txPool, @@ -39,6 +45,7 @@ func NewChain(store Store, txPool *TxPool, eventDispatcher *event.Dispatcher) (* signatureCache: common.NewCache(maxSignatureCacheSize), eventDispatcher: eventDispatcher, processBlockCh: make(chan *processBlockMsg, maxProcessBlockChSize), + knownTxs: knownTxs, } c.cond.L = new(sync.Mutex) @@ -56,7 +63,7 @@ func NewChain(store Store, txPool *TxPool, eventDispatcher *event.Dispatcher) (* return nil, err } - c.bestIrrBlockHeader, err = c.store.GetBlockHeader(storeStatus.IrreversibleHash) + c.lastIrrBlockHeader, err = c.store.GetBlockHeader(storeStatus.IrreversibleHash) if err != nil { return nil, err } @@ -102,7 +109,7 @@ func (c *Chain) BestBlockHeight() uint64 { return c.bestBlockHeader.Height } -// BestBlockHash return the hash of the chain tail block +// BestBlockHash return the hash of the main chain tail block func (c *Chain) BestBlockHash() *bc.Hash { c.cond.L.Lock() defer c.cond.L.Unlock() @@ -110,11 +117,11 @@ func (c *Chain) BestBlockHash() *bc.Hash { return &bestHash } -// BestIrreversibleHeader returns the chain best irreversible block header -func (c *Chain) BestIrreversibleHeader() *types.BlockHeader { +// LastIrreversibleHeader returns the chain last irreversible block header +func (c *Chain) LastIrreversibleHeader() *types.BlockHeader { c.cond.L.Lock() defer c.cond.L.Unlock() - return c.bestIrrBlockHeader + return c.lastIrrBlockHeader } // BestBlockHeader returns the chain best block header @@ -139,6 +146,42 @@ func (c *Chain) InMainChain(hash bc.Hash) bool { return *blockHash == hash } +// trace back to the tail of the chain from the given block header +func (c *Chain) traceLongestChainTail(blockHeader *types.BlockHeader) (*types.BlockHeader, error) { + longestTail, workQueue := blockHeader, []*types.BlockHeader{blockHeader} + + for ; len(workQueue) > 0; workQueue = workQueue[1:] { + currentHeader := workQueue[0] + currentHash := currentHeader.Hash() + hashes, err := c.store.GetBlockHashesByHeight(currentHeader.Height + 1) + if err != nil { + return nil, err + } + + for _, h := range hashes { + if header, err := c.store.GetBlockHeader(h); err != nil { + return nil, err + } else if header.PreviousBlockHash == currentHash { + if longestTail.Height < header.Height { + longestTail = header + } + workQueue = append(workQueue, header) + } + } + } + return longestTail, nil +} + +func (c *Chain) hasSeenTx(tx *types.Tx) bool { + return c.knownTxs.Has(tx.ID.String()) +} + +func (c *Chain) markTransactions(txs ...*types.Tx) { + for _, tx := range txs { + c.knownTxs.Add(tx.ID.String()) + } +} + // This function must be called with mu lock in above level func (c *Chain) setState(blockHeader, irrBlockHeader *types.BlockHeader, mainBlockHeaders []*types.BlockHeader, view *state.UtxoViewpoint, consensusResults []*state.ConsensusResult) error { if err := c.store.SaveChainStatus(blockHeader, irrBlockHeader, mainBlockHeaders, view, consensusResults); err != nil { @@ -146,7 +189,7 @@ func (c *Chain) setState(blockHeader, irrBlockHeader *types.BlockHeader, mainBlo } c.bestBlockHeader = blockHeader - c.bestIrrBlockHeader = irrBlockHeader + c.lastIrrBlockHeader = irrBlockHeader blockHash := blockHeader.Hash() log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("chain best status has been update")