aboutsummaryrefslogtreecommitdiffstats
path: root/consensus/ethash/consensus.go
diff options
context:
space:
mode:
Diffstat (limited to 'consensus/ethash/consensus.go')
-rw-r--r--consensus/ethash/consensus.go50
1 files changed, 40 insertions, 10 deletions
diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go
index e18a06d52..86fd997ae 100644
--- a/consensus/ethash/consensus.go
+++ b/consensus/ethash/consensus.go
@@ -461,6 +461,13 @@ func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
// VerifySeal implements consensus.Engine, checking whether the given block satisfies
// the PoW difficulty requirements.
func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
+ return ethash.verifySeal(chain, header, false)
+}
+
+// verifySeal checks whether a block satisfies the PoW difficulty requirements,
+// either using the usual ethash cache for it, or alternatively using a full DAG
+// to make remote mining fast.
+func (ethash *Ethash) verifySeal(chain consensus.ChainReader, header *types.Header, fulldag bool) error {
// If we're running a fake PoW, accept any seal as valid
if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake {
time.Sleep(ethash.fakeDelay)
@@ -471,25 +478,48 @@ func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Head
}
// If we're running a shared PoW, delegate verification to it
if ethash.shared != nil {
- return ethash.shared.VerifySeal(chain, header)
+ return ethash.shared.verifySeal(chain, header, fulldag)
}
// Ensure that we have a valid difficulty for the block
if header.Difficulty.Sign() <= 0 {
return errInvalidDifficulty
}
- // Recompute the digest and PoW value and verify against the header
+ // Recompute the digest and PoW values
number := header.Number.Uint64()
- cache := ethash.cache(number)
- size := datasetSize(number)
- if ethash.config.PowMode == ModeTest {
- size = 32 * 1024
+ var (
+ digest []byte
+ result []byte
+ )
+ // If fast-but-heavy PoW verification was requested, use an ethash dataset
+ if fulldag {
+ dataset := ethash.dataset(number, true)
+ if dataset.generated() {
+ digest, result = hashimotoFull(dataset.dataset, header.HashNoNonce().Bytes(), header.Nonce.Uint64())
+
+ // Datasets are unmapped in a finalizer. Ensure that the dataset stays alive
+ // until after the call to hashimotoFull so it's not unmapped while being used.
+ runtime.KeepAlive(dataset)
+ } else {
+ // Dataset not yet generated, don't hang, use a cache instead
+ fulldag = false
+ }
}
- digest, result := hashimotoLight(size, cache.cache, header.HashNoNonce().Bytes(), header.Nonce.Uint64())
- // Caches are unmapped in a finalizer. Ensure that the cache stays live
- // until after the call to hashimotoLight so it's not unmapped while being used.
- runtime.KeepAlive(cache)
+ // If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache
+ if !fulldag {
+ cache := ethash.cache(number)
+
+ size := datasetSize(number)
+ if ethash.config.PowMode == ModeTest {
+ size = 32 * 1024
+ }
+ digest, result = hashimotoLight(size, cache.cache, header.HashNoNonce().Bytes(), header.Nonce.Uint64())
+ // Caches are unmapped in a finalizer. Ensure that the cache stays alive
+ // until after the call to hashimotoLight so it's not unmapped while being used.
+ runtime.KeepAlive(cache)
+ }
+ // Verify the calculated values against the ones provided in the header
if !bytes.Equal(header.MixDigest[:], digest) {
return errInvalidMixDigest
}