Skip to content

Commit

Permalink
multi: automate block template generation.
Browse files Browse the repository at this point in the history
  • Loading branch information
dnldd committed May 24, 2018
1 parent 678ff1e commit 9e1f115
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
62 changes: 62 additions & 0 deletions blockmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ const (
// do expensive lottery data look ups for these blocks. It is
// equivalent to 24 hours of work on mainnet.
maxLotteryDataBlockDelta = 288

// templateRegenSeconds is the minimum required number of seconds elapsed
// before a new template is generated when the previous block hash has not
// changed.
templateRegenSeconds = 15
)

// zeroHash is the zero value hash (all zeros). It is defined as a convenience.
Expand Down Expand Up @@ -244,6 +249,12 @@ type pauseMsg struct {
unpause <-chan struct{}
}

// postponeTemplateRegenMsg handles a request to reschedule block template
// regeneration to a future time.
type postponeTemplateRegenMsg struct {
reply chan postponeTemplateRegenResponse
}

// getCurrentTemplateMsg handles a request for the current mining block template.
type getCurrentTemplateMsg struct {
reply chan getCurrentTemplateResponse
Expand All @@ -255,6 +266,12 @@ type getCurrentTemplateResponse struct {
Template *BlockTemplate
}

// postponeTemplateRegenResponse is a response sent to the reply channel of a
// postponeTemplateRegenMsg.
type postponeTemplateRegenResponse struct {
NextTemplateRegen time.Time
}

// setCurrentTemplateMsg handles a request to change the current mining block
// template.
type setCurrentTemplateMsg struct {
Expand Down Expand Up @@ -409,6 +426,12 @@ type blockManager struct {
lotteryDataBroadcast map[chainhash.Hash]struct{}
lotteryDataBroadcastMutex sync.RWMutex

// the following fields handle block template regeneration.
isMining bool
lastRegen time.Time
nextRegen time.Time
regenPostponed bool

cachedCurrentTemplate *BlockTemplate
cachedParentTemplate *BlockTemplate
AggressiveMining bool
Expand Down Expand Up @@ -1633,6 +1656,9 @@ func (b *blockManager) limitMap(m map[chainhash.Hash]struct{}, limit int) {
// the fetching should proceed.
func (b *blockManager) blockHandler() {
candidatePeers := list.New()
ticker := time.NewTicker(time.Second)
b.lastRegen = b.server.txMemPool.LastUpdated()
b.nextRegen = b.lastRegen.Add(time.Second * templateRegenSeconds)
out:
for {
select {
Expand Down Expand Up @@ -1900,6 +1926,16 @@ out:
msg.reply <- getCurrentTemplateResponse{
Template: cur,
}
case postponeTemplateRegenMsg:
futureRegen := b.nextRegen.Add(time.Second * templateRegenSeconds)
if !b.regenPostponed {
b.lastRegen, b.nextRegen = b.nextRegen, futureRegen
b.regenPostponed = true
}

msg.reply <- postponeTemplateRegenResponse{
NextTemplateRegen: b.nextRegen,
}

case setCurrentTemplateMsg:
b.cachedCurrentTemplate = deepCopyBlockTemplate(msg.Template)
Expand All @@ -1920,6 +1956,23 @@ out:
"handler: %T", msg)
}

case <-ticker.C:
mpLastUpdated := b.server.txMemPool.LastUpdated()
// Assert the mempool has been updated since the last block
// template regeneration.
if mpLastUpdated.After(b.lastRegen) {
// Regenerate block template when the threshold is met.
if mpLastUpdated.Equal(b.nextRegen) ||
mpLastUpdated.After(b.nextRegen) {
futureRegen := b.nextRegen.
Add(time.Second * templateRegenSeconds)
if !b.regenPostponed {
b.lastRegen, b.nextRegen = b.nextRegen, futureRegen
b.regenPostponed = true
}
}
}

case <-b.quit:
break out
}
Expand Down Expand Up @@ -2494,6 +2547,15 @@ func (b *blockManager) GetCurrentTemplate() *BlockTemplate {
return response.Template
}

// PostPoneTemplateRegen reschedules the block template generation to
// a future time.
func (b *blockManager) PostponeTemplateRegen() time.Time {
reply := make(chan postponeTemplateRegenResponse)
b.msgChan <- postponeTemplateRegenMsg{reply: reply}
response := <-reply
return response.NextTemplateRegen
}

// SetCurrentTemplate sets the current block template for mining.
func (b *blockManager) SetCurrentTemplate(bt *BlockTemplate) {
reply := make(chan setCurrentTemplateResponse)
Expand Down
10 changes: 10 additions & 0 deletions mempool/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ type Config struct {
// to use for indexing the unconfirmed transactions in the memory pool.
// This can be nil if the address index is not enabled.
ExistsAddrIndex *indexers.ExistsAddrIndex

// PostponeTemplateRegen defines the function to use to signal
// postponing a template regeneration to a future time.
PostponeTemplateRegen func() time.Time
}

// Policy houses the policy (configuration parameters) which is used to
Expand Down Expand Up @@ -610,6 +614,12 @@ func (mp *TxPool) RemoveDoubleSpends(tx *dcrutil.Tx) {
func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint,
tx *dcrutil.Tx, txType stake.TxType, height int64, fee int64) {

if txType != stake.TxTypeSSGen {
futureRegen := mp.cfg.PostponeTemplateRegen()
if futureRegen.After(mp.LastUpdated()) {
log.Info("Block template regeneration postponed to %v", futureRegen)
}
}
// Add the transaction to the pool and mark the referenced outpoints
// as spent by the pool.
msgTx := tx.MsgTx()
Expand Down
3 changes: 3 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2551,6 +2551,9 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
PastMedianTime: func() time.Time { return bm.chain.BestSnapshot().MedianTime },
AddrIndex: s.addrIndex,
ExistsAddrIndex: s.existsAddrIndex,
PostponeTemplateRegen: func() time.Time {
return bm.PostponeTemplateRegen()
},
}
s.txMemPool = mempool.New(&txC)

Expand Down

0 comments on commit 9e1f115

Please sign in to comment.