Skip to content

Commit a91b704

Browse files
authored
consensus/ethash: refactor remote sealer (#20335)
The original idea behind this change was to remove a use of the deprecated CancelRequest method. Simply removing it would've been an option, but I couldn't resist and did a bit of a refactoring instead. All remote sealing code was contained in a single giant function. Remote sealing is now extracted into its own object, remoteSealer.
1 parent c9f28ca commit a91b704

File tree

5 files changed

+294
-304
lines changed

5 files changed

+294
-304
lines changed

consensus/ethash/algorithm_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ func TestConcurrentDiskCacheGeneration(t *testing.T) {
729729

730730
go func(idx int) {
731731
defer pend.Done()
732-
ethash := New(Config{cachedir, 0, 1, "", 0, 0, ModeNormal}, nil, false)
732+
ethash := New(Config{cachedir, 0, 1, "", 0, 0, ModeNormal, nil}, nil, false)
733733
defer ethash.Close()
734734
if err := ethash.VerifySeal(nil, block.Header()); err != nil {
735735
t.Errorf("proc %d: block verification failed: %v", idx, err)

consensus/ethash/api.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var errEthashStopped = errors.New("ethash stopped")
2828

2929
// API exposes ethash related methods for the RPC interface.
3030
type API struct {
31-
ethash *Ethash // Make sure the mode of ethash is normal.
31+
ethash *Ethash
3232
}
3333

3434
// GetWork returns a work package for external miner.
@@ -39,21 +39,19 @@ type API struct {
3939
// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
4040
// result[3] - hex encoded block number
4141
func (api *API) GetWork() ([4]string, error) {
42-
if api.ethash.config.PowMode != ModeNormal && api.ethash.config.PowMode != ModeTest {
42+
if api.ethash.remote == nil {
4343
return [4]string{}, errors.New("not supported")
4444
}
4545

4646
var (
4747
workCh = make(chan [4]string, 1)
4848
errc = make(chan error, 1)
4949
)
50-
5150
select {
52-
case api.ethash.fetchWorkCh <- &sealWork{errc: errc, res: workCh}:
53-
case <-api.ethash.exitCh:
51+
case api.ethash.remote.fetchWorkCh <- &sealWork{errc: errc, res: workCh}:
52+
case <-api.ethash.remote.exitCh:
5453
return [4]string{}, errEthashStopped
5554
}
56-
5755
select {
5856
case work := <-workCh:
5957
return work, nil
@@ -66,23 +64,21 @@ func (api *API) GetWork() ([4]string, error) {
6664
// It returns an indication if the work was accepted.
6765
// Note either an invalid solution, a stale work a non-existent work will return false.
6866
func (api *API) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash) bool {
69-
if api.ethash.config.PowMode != ModeNormal && api.ethash.config.PowMode != ModeTest {
67+
if api.ethash.remote == nil {
7068
return false
7169
}
7270

7371
var errc = make(chan error, 1)
74-
7572
select {
76-
case api.ethash.submitWorkCh <- &mineResult{
73+
case api.ethash.remote.submitWorkCh <- &mineResult{
7774
nonce: nonce,
7875
mixDigest: digest,
7976
hash: hash,
8077
errc: errc,
8178
}:
82-
case <-api.ethash.exitCh:
79+
case <-api.ethash.remote.exitCh:
8380
return false
8481
}
85-
8682
err := <-errc
8783
return err == nil
8884
}
@@ -94,21 +90,19 @@ func (api *API) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash) boo
9490
// It accepts the miner hash rate and an identifier which must be unique
9591
// between nodes.
9692
func (api *API) SubmitHashRate(rate hexutil.Uint64, id common.Hash) bool {
97-
if api.ethash.config.PowMode != ModeNormal && api.ethash.config.PowMode != ModeTest {
93+
if api.ethash.remote == nil {
9894
return false
9995
}
10096

10197
var done = make(chan struct{}, 1)
102-
10398
select {
104-
case api.ethash.submitRateCh <- &hashrate{done: done, rate: uint64(rate), id: id}:
105-
case <-api.ethash.exitCh:
99+
case api.ethash.remote.submitRateCh <- &hashrate{done: done, rate: uint64(rate), id: id}:
100+
case <-api.ethash.remote.exitCh:
106101
return false
107102
}
108103

109104
// Block until hash rate submitted successfully.
110105
<-done
111-
112106
return true
113107
}
114108

consensus/ethash/ethash.go

Lines changed: 34 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ import (
3434
"unsafe"
3535

3636
mmap "github.com/edsrzf/mmap-go"
37-
"github.com/ethereum/go-ethereum/common"
3837
"github.com/ethereum/go-ethereum/consensus"
39-
"github.com/ethereum/go-ethereum/core/types"
4038
"github.com/ethereum/go-ethereum/log"
4139
"github.com/ethereum/go-ethereum/metrics"
4240
"github.com/ethereum/go-ethereum/rpc"
@@ -50,7 +48,7 @@ var (
5048
two256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0))
5149

5250
// sharedEthash is a full instance that can be shared between multiple users.
53-
sharedEthash = New(Config{"", 3, 0, "", 1, 0, ModeNormal}, nil, false)
51+
sharedEthash = New(Config{"", 3, 0, "", 1, 0, ModeNormal, nil}, nil, false)
5452

5553
// algorithmRevision is the data structure version used for file naming.
5654
algorithmRevision = 23
@@ -403,36 +401,8 @@ type Config struct {
403401
DatasetsInMem int
404402
DatasetsOnDisk int
405403
PowMode Mode
406-
}
407-
408-
// sealTask wraps a seal block with relative result channel for remote sealer thread.
409-
type sealTask struct {
410-
block *types.Block
411-
results chan<- *types.Block
412-
}
413-
414-
// mineResult wraps the pow solution parameters for the specified block.
415-
type mineResult struct {
416-
nonce types.BlockNonce
417-
mixDigest common.Hash
418-
hash common.Hash
419-
420-
errc chan error
421-
}
422-
423-
// hashrate wraps the hash rate submitted by the remote sealer.
424-
type hashrate struct {
425-
id common.Hash
426-
ping time.Time
427-
rate uint64
428404

429-
done chan struct{}
430-
}
431-
432-
// sealWork wraps a seal work package for remote sealer.
433-
type sealWork struct {
434-
errc chan error
435-
res chan [4]string
405+
Log log.Logger `toml:"-"`
436406
}
437407

438408
// Ethash is a consensus engine based on proof-of-work implementing the ethash
@@ -448,72 +418,56 @@ type Ethash struct {
448418
threads int // Number of threads to mine on if mining
449419
update chan struct{} // Notification channel to update mining parameters
450420
hashrate metrics.Meter // Meter tracking the average hashrate
451-
452-
// Remote sealer related fields
453-
workCh chan *sealTask // Notification channel to push new work and relative result channel to remote sealer
454-
fetchWorkCh chan *sealWork // Channel used for remote sealer to fetch mining work
455-
submitWorkCh chan *mineResult // Channel used for remote sealer to submit their mining result
456-
fetchRateCh chan chan uint64 // Channel used to gather submitted hash rate for local or remote sealer.
457-
submitRateCh chan *hashrate // Channel used for remote sealer to submit their mining hashrate
421+
remote *remoteSealer
458422

459423
// The fields below are hooks for testing
460424
shared *Ethash // Shared PoW verifier to avoid cache regeneration
461425
fakeFail uint64 // Block number which fails PoW check even in fake mode
462426
fakeDelay time.Duration // Time delay to sleep for before returning from verify
463427

464-
lock sync.Mutex // Ensures thread safety for the in-memory caches and mining fields
465-
closeOnce sync.Once // Ensures exit channel will not be closed twice.
466-
exitCh chan chan error // Notification channel to exiting backend threads
428+
lock sync.Mutex // Ensures thread safety for the in-memory caches and mining fields
429+
closeOnce sync.Once // Ensures exit channel will not be closed twice.
467430
}
468431

469432
// New creates a full sized ethash PoW scheme and starts a background thread for
470433
// remote mining, also optionally notifying a batch of remote services of new work
471434
// packages.
472435
func New(config Config, notify []string, noverify bool) *Ethash {
436+
if config.Log == nil {
437+
config.Log = log.Root()
438+
}
473439
if config.CachesInMem <= 0 {
474-
log.Warn("One ethash cache must always be in memory", "requested", config.CachesInMem)
440+
config.Log.Warn("One ethash cache must always be in memory", "requested", config.CachesInMem)
475441
config.CachesInMem = 1
476442
}
477443
if config.CacheDir != "" && config.CachesOnDisk > 0 {
478-
log.Info("Disk storage enabled for ethash caches", "dir", config.CacheDir, "count", config.CachesOnDisk)
444+
config.Log.Info("Disk storage enabled for ethash caches", "dir", config.CacheDir, "count", config.CachesOnDisk)
479445
}
480446
if config.DatasetDir != "" && config.DatasetsOnDisk > 0 {
481-
log.Info("Disk storage enabled for ethash DAGs", "dir", config.DatasetDir, "count", config.DatasetsOnDisk)
447+
config.Log.Info("Disk storage enabled for ethash DAGs", "dir", config.DatasetDir, "count", config.DatasetsOnDisk)
482448
}
483449
ethash := &Ethash{
484-
config: config,
485-
caches: newlru("cache", config.CachesInMem, newCache),
486-
datasets: newlru("dataset", config.DatasetsInMem, newDataset),
487-
update: make(chan struct{}),
488-
hashrate: metrics.NewMeterForced(),
489-
workCh: make(chan *sealTask),
490-
fetchWorkCh: make(chan *sealWork),
491-
submitWorkCh: make(chan *mineResult),
492-
fetchRateCh: make(chan chan uint64),
493-
submitRateCh: make(chan *hashrate),
494-
exitCh: make(chan chan error),
495-
}
496-
go ethash.remote(notify, noverify)
450+
config: config,
451+
caches: newlru("cache", config.CachesInMem, newCache),
452+
datasets: newlru("dataset", config.DatasetsInMem, newDataset),
453+
update: make(chan struct{}),
454+
hashrate: metrics.NewMeterForced(),
455+
}
456+
ethash.remote = startRemoteSealer(ethash, notify, noverify)
497457
return ethash
498458
}
499459

500460
// NewTester creates a small sized ethash PoW scheme useful only for testing
501461
// purposes.
502462
func NewTester(notify []string, noverify bool) *Ethash {
503463
ethash := &Ethash{
504-
config: Config{PowMode: ModeTest},
505-
caches: newlru("cache", 1, newCache),
506-
datasets: newlru("dataset", 1, newDataset),
507-
update: make(chan struct{}),
508-
hashrate: metrics.NewMeterForced(),
509-
workCh: make(chan *sealTask),
510-
fetchWorkCh: make(chan *sealWork),
511-
submitWorkCh: make(chan *mineResult),
512-
fetchRateCh: make(chan chan uint64),
513-
submitRateCh: make(chan *hashrate),
514-
exitCh: make(chan chan error),
515-
}
516-
go ethash.remote(notify, noverify)
464+
config: Config{PowMode: ModeTest, Log: log.Root()},
465+
caches: newlru("cache", 1, newCache),
466+
datasets: newlru("dataset", 1, newDataset),
467+
update: make(chan struct{}),
468+
hashrate: metrics.NewMeterForced(),
469+
}
470+
ethash.remote = startRemoteSealer(ethash, notify, noverify)
517471
return ethash
518472
}
519473

@@ -524,6 +478,7 @@ func NewFaker() *Ethash {
524478
return &Ethash{
525479
config: Config{
526480
PowMode: ModeFake,
481+
Log: log.Root(),
527482
},
528483
}
529484
}
@@ -535,6 +490,7 @@ func NewFakeFailer(fail uint64) *Ethash {
535490
return &Ethash{
536491
config: Config{
537492
PowMode: ModeFake,
493+
Log: log.Root(),
538494
},
539495
fakeFail: fail,
540496
}
@@ -547,6 +503,7 @@ func NewFakeDelayer(delay time.Duration) *Ethash {
547503
return &Ethash{
548504
config: Config{
549505
PowMode: ModeFake,
506+
Log: log.Root(),
550507
},
551508
fakeDelay: delay,
552509
}
@@ -558,6 +515,7 @@ func NewFullFaker() *Ethash {
558515
return &Ethash{
559516
config: Config{
560517
PowMode: ModeFullFake,
518+
Log: log.Root(),
561519
},
562520
}
563521
}
@@ -573,13 +531,11 @@ func (ethash *Ethash) Close() error {
573531
var err error
574532
ethash.closeOnce.Do(func() {
575533
// Short circuit if the exit channel is not allocated.
576-
if ethash.exitCh == nil {
534+
if ethash.remote == nil {
577535
return
578536
}
579-
errc := make(chan error)
580-
ethash.exitCh <- errc
581-
err = <-errc
582-
close(ethash.exitCh)
537+
close(ethash.remote.requestExit)
538+
<-ethash.remote.exitCh
583539
})
584540
return err
585541
}
@@ -680,8 +636,8 @@ func (ethash *Ethash) Hashrate() float64 {
680636
var res = make(chan uint64, 1)
681637

682638
select {
683-
case ethash.fetchRateCh <- res:
684-
case <-ethash.exitCh:
639+
case ethash.remote.fetchRateCh <- res:
640+
case <-ethash.remote.exitCh:
685641
// Return local hashrate only if ethash is stopped.
686642
return ethash.hashrate.Rate1()
687643
}

0 commit comments

Comments
 (0)