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 }