github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/chain_pow.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"runtime"
    21  
    22  	"github.com/ethereumproject/go-ethereum/core/types"
    23  	"github.com/ethereumproject/go-ethereum/pow"
    24  )
    25  
    26  // nonceCheckResult contains the result of a nonce verification.
    27  type nonceCheckResult struct {
    28  	index int  // Index of the item verified from an input array
    29  	valid bool // Result of the nonce verification
    30  }
    31  
    32  // verifyNoncesFromHeaders starts a concurrent header nonce verification,
    33  // returning a quit channel to abort the operations and a results channel
    34  // to retrieve the async verifications.
    35  func verifyNoncesFromHeaders(checker pow.PoW, headers []*types.Header) (chan<- struct{}, <-chan nonceCheckResult) {
    36  	items := make([]pow.Block, len(headers))
    37  	for i, header := range headers {
    38  		items[i] = types.NewBlockWithHeader(header)
    39  	}
    40  	return verifyNonces(checker, items)
    41  }
    42  
    43  // verifyNoncesFromBlocks starts a concurrent block nonce verification,
    44  // returning a quit channel to abort the operations and a results channel
    45  // to retrieve the async verifications.
    46  func verifyNoncesFromBlocks(checker pow.PoW, blocks []*types.Block) (chan<- struct{}, <-chan nonceCheckResult) {
    47  	items := make([]pow.Block, len(blocks))
    48  	for i, block := range blocks {
    49  		items[i] = block
    50  	}
    51  	return verifyNonces(checker, items)
    52  }
    53  
    54  // verifyNonces starts a concurrent nonce verification, returning a quit channel
    55  // to abort the operations and a results channel to retrieve the async checks.
    56  func verifyNonces(checker pow.PoW, items []pow.Block) (chan<- struct{}, <-chan nonceCheckResult) {
    57  	// Spawn as many workers as allowed threads
    58  	workers := runtime.GOMAXPROCS(0)
    59  	if len(items) < workers {
    60  		workers = len(items)
    61  	}
    62  	// Create a task channel and spawn the verifiers
    63  	tasks := make(chan int, workers)
    64  	results := make(chan nonceCheckResult, len(items)) // Buffered to make sure all workers stop
    65  	for i := 0; i < workers; i++ {
    66  		go func() {
    67  			for index := range tasks {
    68  				results <- nonceCheckResult{index: index, valid: checker.Verify(items[index])}
    69  			}
    70  		}()
    71  	}
    72  	// Feed item indices to the workers until done or aborted
    73  	abort := make(chan struct{})
    74  	go func() {
    75  		defer close(tasks)
    76  
    77  		for i := range items {
    78  			select {
    79  			case tasks <- i:
    80  				continue
    81  			case <-abort:
    82  				return
    83  			}
    84  		}
    85  	}()
    86  	return abort, results
    87  }