Skip to content

Commit

Permalink
blockmanager: remove block manager chain state.
Browse files Browse the repository at this point in the history
Port of upstream commit 2274d36 (subset).
  • Loading branch information
dnldd committed Sep 12, 2018
1 parent 346e582 commit f080ee3
Showing 1 changed file with 41 additions and 278 deletions.
319 changes: 41 additions & 278 deletions blockmanager.go
Expand Up @@ -296,85 +296,6 @@ type headerNode struct {
hash *chainhash.Hash
}

// chainState tracks the state of the best chain as blocks are inserted. This
// is done because blockchain is currently not safe for concurrent access and the
// block manager is typically quite busy processing block and inventory.
// Therefore, requesting this information from chain through the block manager
// would not be anywhere near as efficient as simply updating it as each block
// is inserted and protecting it with a mutex.
type chainState struct {
sync.Mutex
newestHash *chainhash.Hash
newestHeight int64
nextFinalState [6]byte
nextPoolSize uint32
nextStakeDifficulty int64
winningTickets []chainhash.Hash
missedTickets []chainhash.Hash
curPrevHash chainhash.Hash
pastMedianTime time.Time
}

// Best returns the block hash and height known for the tip of the best known
// chain.
//
// This function is safe for concurrent access.
func (c *chainState) Best() (*chainhash.Hash, int64) {
c.Lock()
defer c.Unlock()

return c.newestHash, c.newestHeight
}

// NextWPO returns next winner, potential, and overflow for the current top block
// of the blockchain.
//
// This function is safe for concurrent access.
func (c *chainState) NextFinalState() [6]byte {
c.Lock()
defer c.Unlock()

return c.nextFinalState
}

func (c *chainState) NextPoolSize() uint32 {
c.Lock()
defer c.Unlock()

return c.nextPoolSize
}

// NextWinners returns the eligible SStx hashes to vote on the
// next block as inputs for SSGen.
//
// This function is safe for concurrent access.
func (c *chainState) NextWinners() []chainhash.Hash {
c.Lock()
defer c.Unlock()

return c.winningTickets
}

// CurrentlyMissed returns the eligible SStx hashes that can be revoked.
//
// This function is safe for concurrent access.
func (c *chainState) CurrentlyMissed() []chainhash.Hash {
c.Lock()
defer c.Unlock()

return c.missedTickets
}

// GetTopPrevHash returns the current previous block hash.
//
// This function is safe for concurrent access.
func (c *chainState) GetTopPrevHash() chainhash.Hash {
c.Lock()
defer c.Unlock()

return c.curPrevHash
}

// blockManager provides a concurrency safe block manager for handling all
// incoming blocks.
type blockManager struct {
Expand All @@ -390,7 +311,6 @@ type blockManager struct {
progressLogger *blockProgressLogger
syncPeer *serverPeer
msgChan chan interface{}
chainState chainState
wg sync.WaitGroup
quit chan struct{}

Expand Down Expand Up @@ -428,29 +348,6 @@ func (b *blockManager) resetHeaderState(newestHash *chainhash.Hash, newestHeight
}
}

// updateChainState updates the chain state associated with the block manager.
// This allows fast access to chain information since blockchain is currently not
// safe for concurrent access and the block manager is typically quite busy
// processing block and inventory.
func (b *blockManager) updateChainState(newestHash *chainhash.Hash,
newestHeight int64, finalState [6]byte, poolSize uint32,
nextStakeDiff int64, winningTickets []chainhash.Hash,
missedTickets []chainhash.Hash, curPrevHash chainhash.Hash) {

b.chainState.Lock()
defer b.chainState.Unlock()

b.chainState.newestHash = newestHash
b.chainState.newestHeight = newestHeight
b.chainState.pastMedianTime = b.chain.BestSnapshot().MedianTime
b.chainState.nextFinalState = finalState
b.chainState.nextPoolSize = poolSize
b.chainState.nextStakeDifficulty = nextStakeDiff
b.chainState.winningTickets = winningTickets
b.chainState.missedTickets = missedTickets
b.chainState.curPrevHash = curPrevHash
}

// findNextHeaderCheckpoint returns the next checkpoint after the passed height.
// It returns nil when there is not one either because the height is already
// later than the final checkpoint or some other reason such as disabled
Expand Down Expand Up @@ -1077,54 +974,23 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
b.checkBlockForHiddenVotes(bmsg.block)
}

// Query the db for the latest best block since the block
// that was processed could be on a side chain or have caused
// a reorg.
// Notify stake difficulty subscribers and prune invalidated
// transactions.
best := b.chain.BestSnapshot()

// Query the DB for the missed tickets for the next top block.
missedTickets, err := b.chain.MissedTickets()
if err != nil {
bmgrLog.Warnf("Failed to get missed tickets "+
"for best block %v: %v", best.Hash, err)
}

// Retrieve the current previous block hash.
curPrevHash := b.chain.BestPrevHash()

nextStakeDiff, err :=
b.chain.CalcNextRequiredStakeDifficulty()
if err != nil {
bmgrLog.Warnf("Failed to get next stake difficulty "+
"calculation: %v", err)
}
if err == nil {
r := b.server.rpcServer
if r != nil {
// Update registered websocket clients on the
// current stake difficulty.
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
best.Hash,
best.Height,
nextStakeDiff,
})
}
b.server.txMemPool.PruneStakeTx(nextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
}

winningTickets, poolSize, finalState, err :=
b.chain.LotteryDataForBlock(blockHash)
if err != nil {
bmgrLog.Warnf("Failed to get determine lottery "+
"data for new best block: %v", err)
r := b.server.rpcServer
if r != nil {
// Update registered websocket clients on the
// current stake difficulty.
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
best.Hash,
best.Height,
best.NextStakeDiff,
})
}

b.updateChainState(&best.Hash, best.Height, finalState,
uint32(poolSize), nextStakeDiff, winningTickets,
missedTickets, curPrevHash)
b.server.txMemPool.PruneStakeTx(best.NextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()

// Update this peer's latest block height, for future
// potential sync node candidancy.
Expand Down Expand Up @@ -1646,60 +1512,22 @@ out:
err := b.chain.ForceHeadReorganization(
msg.formerBest, msg.newBest)

// Reorganizing has succeeded, so we need to
// update the chain state.
if err == nil {
// Query the db for the latest best block since
// the block that was processed could be on a
// side chain or have caused a reorg.
// Notify stake difficulty subscribers and prune
// invalidated transactions.
best := b.chain.BestSnapshot()

// Fetch the required lottery data.
winningTickets, poolSize, finalState, err :=
b.chain.LotteryDataForBlock(&best.Hash)

// Update registered websocket clients on the
// current stake difficulty.
nextStakeDiff, errSDiff :=
b.chain.CalcNextRequiredStakeDifficulty()
if err != nil {
bmgrLog.Warnf("Failed to get next stake difficulty "+
"calculation: %v", err)
r := b.server.rpcServer
if r != nil {
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
best.Hash,
best.Height,
best.NextStakeDiff,
})
}
if errSDiff == nil {
r := b.server.rpcServer
if r != nil {
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
best.Hash,
best.Height,
nextStakeDiff,
})
}
b.server.txMemPool.PruneStakeTx(nextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
}

missedTickets, err := b.chain.MissedTickets()
if err != nil {
bmgrLog.Warnf("Failed to get missed tickets"+
": %v", err)
}

// The blockchain should be updated, so fetch the
// latest snapshot.
best = b.chain.BestSnapshot()
curPrevHash := b.chain.BestPrevHash()

b.updateChainState(&best.Hash,
best.Height,
finalState,
uint32(poolSize),
nextStakeDiff,
winningTickets,
missedTickets,
curPrevHash)
b.server.txMemPool.PruneStakeTx(best.NextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
}

msg.reply <- forceReorganizationResponse{
Expand All @@ -1725,60 +1553,23 @@ out:
continue
}

// If the block added to the main chain, then we need to
// update the tip locally on block manager.
onMainChain := !isOrphan && forkLen == 0
if onMainChain {
// Query the chain for the latest best block
// since the block that was processed could be
// on a side chain or have caused a reorg.
// Notify stake difficulty subscribers and prune
// invalidated transactions.
best := b.chain.BestSnapshot()

// Update registered websocket clients on the
// current stake difficulty.
nextStakeDiff, err :=
b.chain.CalcNextRequiredStakeDifficulty()
if err != nil {
bmgrLog.Warnf("Failed to get next stake difficulty "+
"calculation: %v", err)
} else {
r := b.server.rpcServer
if r != nil {
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
best.Hash,
best.Height,
nextStakeDiff,
})
}
b.server.txMemPool.PruneStakeTx(nextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
}

missedTickets, err := b.chain.MissedTickets()
if err != nil {
bmgrLog.Warnf("Failed to get missing tickets for "+
"incoming block %v: %v", best.Hash, err)
}
curPrevHash := b.chain.BestPrevHash()

winningTickets, poolSize, finalState, err :=
b.chain.LotteryDataForBlock(msg.block.Hash())
if err != nil {
bmgrLog.Warnf("Failed to determine block "+
"lottery data for incoming best block %v: %v",
best.Hash, err)
r := b.server.rpcServer
if r != nil {
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
best.Hash,
best.Height,
best.NextStakeDiff,
})
}

b.updateChainState(&best.Hash,
best.Height,
finalState,
uint32(poolSize),
nextStakeDiff,
winningTickets,
missedTickets,
curPrevHash)
b.server.txMemPool.PruneStakeTx(best.NextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
}

// Allow any clients performing long polling via the
Expand Down Expand Up @@ -2501,34 +2292,6 @@ func newBlockManager(s *server, indexManager blockchain.IndexManager, interrupt
return nil, fmt.Errorf("closing after dumping blockchain")
}

// Query the DB for the current winning ticket data.
wt, ps, fs, err := bm.chain.LotteryDataForBlock(&best.Hash)
if err != nil {
return nil, err
}

// Query the DB for the currently missed tickets.
missedTickets, err := bm.chain.MissedTickets()
if err != nil {
return nil, err
}

// Retrieve the current previous block hash and next stake difficulty.
curPrevHash := bm.chain.BestPrevHash()
nextStakeDiff, err := bm.chain.CalcNextRequiredStakeDifficulty()
if err != nil {
return nil, err
}
bmgrLog.Infof("Next required Stake difficulty: %d", nextStakeDiff)

bm.updateChainState(&best.Hash,
best.Height,
fs,
uint32(ps),
nextStakeDiff,
wt,
missedTickets,
curPrevHash)
bm.lotteryDataBroadcast = make(map[chainhash.Hash]struct{})

return &bm, nil
Expand Down

0 comments on commit f080ee3

Please sign in to comment.