123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- // Copyright 2018 The go-ethereum Authors
- // This file is part of the go-ethereum library.
- //
- // The go-ethereum library is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // The go-ethereum library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
- package core
- import (
- "runtime"
- "github.com/ethereum/go-ethereum/core/types"
- )
- // senderCacher is a concurrent transaction sender recoverer and cacher.
- var senderCacher = newTxSenderCacher(runtime.NumCPU())
- // txSenderCacherRequest is a request for recovering transaction senders with a
- // specific signature scheme and caching it into the transactions themselves.
- //
- // The inc field defines the number of transactions to skip after each recovery,
- // which is used to feed the same underlying input array to different threads but
- // ensure they process the early transactions fast.
- type txSenderCacherRequest struct {
- signer types.Signer
- txs []*types.Transaction
- inc int
- }
- // txSenderCacher is a helper structure to concurrently ecrecover transaction
- // senders from digital signatures on background threads.
- type txSenderCacher struct {
- threads int
- tasks chan *txSenderCacherRequest
- }
- // newTxSenderCacher creates a new transaction sender background cacher and starts
- // as many processing goroutines as allowed by the GOMAXPROCS on construction.
- func newTxSenderCacher(threads int) *txSenderCacher {
- cacher := &txSenderCacher{
- tasks: make(chan *txSenderCacherRequest, threads),
- threads: threads,
- }
- for i := 0; i < threads; i++ {
- go cacher.cache()
- }
- return cacher
- }
- // cache is an infinite loop, caching transaction senders from various forms of
- // data structures.
- func (cacher *txSenderCacher) cache() {
- for task := range cacher.tasks {
- for i := 0; i < len(task.txs); i += task.inc {
- types.Sender(task.signer, task.txs[i])
- }
- }
- }
- // recover recovers the senders from a batch of transactions and caches them
- // back into the same data structures. There is no validation being done, nor
- // any reaction to invalid signatures. That is up to calling code later.
- func (cacher *txSenderCacher) recover(signer types.Signer, txs []*types.Transaction) {
- // If there's nothing to recover, abort
- if len(txs) == 0 {
- return
- }
- // Ensure we have meaningful task sizes and schedule the recoveries
- tasks := cacher.threads
- if len(txs) < tasks*4 {
- tasks = (len(txs) + 3) / 4
- }
- for i := 0; i < tasks; i++ {
- cacher.tasks <- &txSenderCacherRequest{
- signer: signer,
- txs: txs[i:],
- inc: tasks,
- }
- }
- }
- // recoverFromBlocks recovers the senders from a batch of blocks and caches them
- // back into the same data structures. There is no validation being done, nor
- // any reaction to invalid signatures. That is up to calling code later.
- func (cacher *txSenderCacher) recoverFromBlocks(signer types.Signer, blocks []*types.Block) {
- count := 0
- for _, block := range blocks {
- count += len(block.Transactions())
- }
- txs := make([]*types.Transaction, 0, count)
- for _, block := range blocks {
- txs = append(txs, block.Transactions()...)
- }
- cacher.recover(signer, txs)
- }
|