diff options
Diffstat (limited to 'consensus/ethash/ethash.go')
-rw-r--r-- | consensus/ethash/ethash.go | 117 |
1 files changed, 73 insertions, 44 deletions
diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go index dd6147072..a78b3a895 100644 --- a/consensus/ethash/ethash.go +++ b/consensus/ethash/ethash.go @@ -45,7 +45,7 @@ var ( maxUint256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) // sharedEthash is a full instance that can be shared between multiple users. - sharedEthash = New("", 3, 0, "", 1, 0) + sharedEthash = New(Config{"", 3, 0, "", 1, 0, ModeNormal}) // algorithmRevision is the data structure version used for file naming. algorithmRevision = 23 @@ -320,15 +320,32 @@ func MakeDataset(block uint64, dir string) { d.release() } +// Mode defines the type and amount of PoW verification an ethash engine makes. +type Mode uint + +const ( + ModeNormal Mode = iota + ModeShared + ModeTest + ModeFake + ModeFullFake +) + +// Config are the configuration parameters of the ethash. +type Config struct { + CacheDir string + CachesInMem int + CachesOnDisk int + DatasetDir string + DatasetsInMem int + DatasetsOnDisk int + PowMode Mode +} + // Ethash is a consensus engine based on proot-of-work implementing the ethash // algorithm. type Ethash struct { - cachedir string // Data directory to store the verification caches - cachesinmem int // Number of caches to keep in memory - cachesondisk int // Number of caches to keep on disk - dagdir string // Data directory to store full mining datasets - dagsinmem int // Number of mining datasets to keep in memory - dagsondisk int // Number of mining datasets to keep on disk + config Config caches map[uint64]*cache // In memory caches to avoid regenerating too often fcache *cache // Pre-generated cache for the estimated future epoch @@ -342,10 +359,7 @@ type Ethash struct { hashrate metrics.Meter // Meter tracking the average hashrate // The fields below are hooks for testing - tester bool // Flag whether to use a smaller test dataset shared *Ethash // Shared PoW verifier to avoid cache regeneration - fakeMode bool // Flag whether to disable PoW checking - fakeFull bool // Flag whether to disable all consensus rules fakeFail uint64 // Block number which fails PoW check even in fake mode fakeDelay time.Duration // Time delay to sleep for before returning from verify @@ -353,28 +367,23 @@ type Ethash struct { } // New creates a full sized ethash PoW scheme. -func New(cachedir string, cachesinmem, cachesondisk int, dagdir string, dagsinmem, dagsondisk int) *Ethash { - if cachesinmem <= 0 { - log.Warn("One ethash cache must always be in memory", "requested", cachesinmem) - cachesinmem = 1 +func New(config Config) *Ethash { + if config.CachesInMem <= 0 { + log.Warn("One ethash cache must always be in memory", "requested", config.CachesInMem) + config.CachesInMem = 1 } - if cachedir != "" && cachesondisk > 0 { - log.Info("Disk storage enabled for ethash caches", "dir", cachedir, "count", cachesondisk) + if config.CacheDir != "" && config.CachesOnDisk > 0 { + log.Info("Disk storage enabled for ethash caches", "dir", config.CacheDir, "count", config.CachesOnDisk) } - if dagdir != "" && dagsondisk > 0 { - log.Info("Disk storage enabled for ethash DAGs", "dir", dagdir, "count", dagsondisk) + if config.DatasetDir != "" && config.DatasetsOnDisk > 0 { + log.Info("Disk storage enabled for ethash DAGs", "dir", config.DatasetDir, "count", config.DatasetsOnDisk) } return &Ethash{ - cachedir: cachedir, - cachesinmem: cachesinmem, - cachesondisk: cachesondisk, - dagdir: dagdir, - dagsinmem: dagsinmem, - dagsondisk: dagsondisk, - caches: make(map[uint64]*cache), - datasets: make(map[uint64]*dataset), - update: make(chan struct{}), - hashrate: metrics.NewMeter(), + config: config, + caches: make(map[uint64]*cache), + datasets: make(map[uint64]*dataset), + update: make(chan struct{}), + hashrate: metrics.NewMeter(), } } @@ -382,12 +391,14 @@ func New(cachedir string, cachesinmem, cachesondisk int, dagdir string, dagsinme // purposes. func NewTester() *Ethash { return &Ethash{ - cachesinmem: 1, - caches: make(map[uint64]*cache), - datasets: make(map[uint64]*dataset), - tester: true, - update: make(chan struct{}), - hashrate: metrics.NewMeter(), + config: Config{ + CachesInMem: 1, + PowMode: ModeTest, + }, + caches: make(map[uint64]*cache), + datasets: make(map[uint64]*dataset), + update: make(chan struct{}), + hashrate: metrics.NewMeter(), } } @@ -395,27 +406,45 @@ func NewTester() *Ethash { // all blocks' seal as valid, though they still have to conform to the Ethereum // consensus rules. func NewFaker() *Ethash { - return &Ethash{fakeMode: true} + return &Ethash{ + config: Config{ + PowMode: ModeFake, + }, + } } // NewFakeFailer creates a ethash consensus engine with a fake PoW scheme that // accepts all blocks as valid apart from the single one specified, though they // still have to conform to the Ethereum consensus rules. func NewFakeFailer(fail uint64) *Ethash { - return &Ethash{fakeMode: true, fakeFail: fail} + return &Ethash{ + config: Config{ + PowMode: ModeFake, + }, + fakeFail: fail, + } } // NewFakeDelayer creates a ethash consensus engine with a fake PoW scheme that // accepts all blocks as valid, but delays verifications by some time, though // they still have to conform to the Ethereum consensus rules. func NewFakeDelayer(delay time.Duration) *Ethash { - return &Ethash{fakeMode: true, fakeDelay: delay} + return &Ethash{ + config: Config{ + PowMode: ModeFake, + }, + fakeDelay: delay, + } } // NewFullFaker creates an ethash consensus engine with a full fake scheme that // accepts all blocks as valid, without checking any consensus rules whatsoever. func NewFullFaker() *Ethash { - return &Ethash{fakeMode: true, fakeFull: true} + return &Ethash{ + config: Config{ + PowMode: ModeFullFake, + }, + } } // NewShared creates a full sized ethash PoW shared between all requesters running @@ -436,7 +465,7 @@ func (ethash *Ethash) cache(block uint64) []uint32 { current, future := ethash.caches[epoch], (*cache)(nil) if current == nil { // No in-memory cache, evict the oldest if the cache limit was reached - for len(ethash.caches) > 0 && len(ethash.caches) >= ethash.cachesinmem { + for len(ethash.caches) > 0 && len(ethash.caches) >= ethash.config.CachesInMem { var evict *cache for _, cache := range ethash.caches { if evict == nil || evict.used.After(cache.used) { @@ -473,7 +502,7 @@ func (ethash *Ethash) cache(block uint64) []uint32 { ethash.lock.Unlock() // Wait for generation finish, bump the timestamp and finalize the cache - current.generate(ethash.cachedir, ethash.cachesondisk, ethash.tester) + current.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.PowMode == ModeTest) current.lock.Lock() current.used = time.Now() @@ -481,7 +510,7 @@ func (ethash *Ethash) cache(block uint64) []uint32 { // If we exhausted the future cache, now's a good time to regenerate it if future != nil { - go future.generate(ethash.cachedir, ethash.cachesondisk, ethash.tester) + go future.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.PowMode == ModeTest) } return current.cache } @@ -498,7 +527,7 @@ func (ethash *Ethash) dataset(block uint64) []uint32 { current, future := ethash.datasets[epoch], (*dataset)(nil) if current == nil { // No in-memory dataset, evict the oldest if the dataset limit was reached - for len(ethash.datasets) > 0 && len(ethash.datasets) >= ethash.dagsinmem { + for len(ethash.datasets) > 0 && len(ethash.datasets) >= ethash.config.DatasetsInMem { var evict *dataset for _, dataset := range ethash.datasets { if evict == nil || evict.used.After(dataset.used) { @@ -536,7 +565,7 @@ func (ethash *Ethash) dataset(block uint64) []uint32 { ethash.lock.Unlock() // Wait for generation finish, bump the timestamp and finalize the cache - current.generate(ethash.dagdir, ethash.dagsondisk, ethash.tester) + current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.PowMode == ModeTest) current.lock.Lock() current.used = time.Now() @@ -544,7 +573,7 @@ func (ethash *Ethash) dataset(block uint64) []uint32 { // If we exhausted the future dataset, now's a good time to regenerate it if future != nil { - go future.generate(ethash.dagdir, ethash.dagsondisk, ethash.tester) + go future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.PowMode == ModeTest) } return current.dataset } |