github.com/ubiq/go-ethereum@v3.0.1+incompatible/consensus/ubqhash/consensus.go (about)

     1  // Copyright 2017 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 ubqhash
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"math/big"
    24  	"runtime"
    25  	"time"
    26  
    27  	mapset "github.com/deckarep/golang-set"
    28  	"github.com/ubiq/go-ubiq/common"
    29  	"github.com/ubiq/go-ubiq/consensus"
    30  	"github.com/ubiq/go-ubiq/consensus/misc"
    31  	"github.com/ubiq/go-ubiq/core/state"
    32  	"github.com/ubiq/go-ubiq/core/types"
    33  	"github.com/ubiq/go-ubiq/log"
    34  	"github.com/ubiq/go-ubiq/params"
    35  	"github.com/ubiq/go-ubiq/rlp"
    36  	"golang.org/x/crypto/sha3"
    37  )
    38  
    39  // Ubqhash proof-of-work protocol constants.
    40  var (
    41  	maxUncles              = 2                // Maximum number of uncles allowed in a single block
    42  	allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks
    43  )
    44  
    45  // Diff algo constants.
    46  var (
    47  	big88 = big.NewInt(88)
    48  
    49  	digishieldV3Config = &diffConfig{
    50  		AveragingWindow: big.NewInt(21),
    51  		MaxAdjustDown:   big.NewInt(16), // 16%
    52  		MaxAdjustUp:     big.NewInt(8),  // 8%
    53  		Factor:          big.NewInt(100),
    54  	}
    55  
    56  	digishieldV3ModConfig = &diffConfig{
    57  		AveragingWindow: big.NewInt(88),
    58  		MaxAdjustDown:   big.NewInt(3), // 3%
    59  		MaxAdjustUp:     big.NewInt(2), // 2%
    60  		Factor:          big.NewInt(100),
    61  	}
    62  
    63  	fluxConfig = &diffConfig{
    64  		AveragingWindow: big.NewInt(88),
    65  		MaxAdjustDown:   big.NewInt(5), // 0.5%
    66  		MaxAdjustUp:     big.NewInt(3), // 0.3%
    67  		Dampen:          big.NewInt(1), // 0.1%
    68  		Factor:          big.NewInt(1000),
    69  	}
    70  )
    71  
    72  type diffConfig struct {
    73  	AveragingWindow *big.Int `json:"averagingWindow"`
    74  	MaxAdjustDown   *big.Int `json:"maxAdjustDown"`
    75  	MaxAdjustUp     *big.Int `json:"maxAdjustUp"`
    76  	Dampen          *big.Int `json:"dampen,omitempty"`
    77  	Factor          *big.Int `json:"factor"`
    78  }
    79  
    80  // Various error messages to mark blocks invalid. These should be private to
    81  // prevent engine specific errors from being referenced in the remainder of the
    82  // codebase, inherently breaking if the engine is swapped out. Please put common
    83  // error types into the consensus package.
    84  var (
    85  	errZeroBlockTime     = errors.New("timestamp equals parent's")
    86  	errTooManyUncles     = errors.New("too many uncles")
    87  	errDuplicateUncle    = errors.New("duplicate uncle")
    88  	errUncleIsAncestor   = errors.New("uncle is ancestor")
    89  	errDanglingUncle     = errors.New("uncle's parent is not ancestor")
    90  	errInvalidDifficulty = errors.New("non-positive difficulty")
    91  	errInvalidMixDigest  = errors.New("invalid mix digest")
    92  	errInvalidPoW        = errors.New("invalid proof-of-work")
    93  )
    94  
    95  // Author implements consensus.Engine, returning the header's coinbase as the
    96  // proof-of-work verified author of the block.
    97  func (ubqhash *Ubqhash) Author(header *types.Header) (common.Address, error) {
    98  	return header.Coinbase, nil
    99  }
   100  
   101  // VerifyHeader checks whether a header conforms to the consensus rules of the
   102  // stock Ethereum ubqhash engine.
   103  func (ubqhash *Ubqhash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
   104  	// If we're running a full engine faking, accept any input as valid
   105  	if ubqhash.config.PowMode == ModeFullFake {
   106  		return nil
   107  	}
   108  	// Short circuit if the header is known, or it's parent not
   109  	number := header.Number.Uint64()
   110  	if chain.GetHeader(header.Hash(), number) != nil {
   111  		return nil
   112  	}
   113  	parent := chain.GetHeader(header.ParentHash, number-1)
   114  	if parent == nil {
   115  		return consensus.ErrUnknownAncestor
   116  	}
   117  	// Sanity checks passed, do a proper verification
   118  	return ubqhash.verifyHeader(chain, header, parent, false, seal)
   119  }
   120  
   121  // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
   122  // concurrently. The method returns a quit channel to abort the operations and
   123  // a results channel to retrieve the async verifications.
   124  func (ubqhash *Ubqhash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
   125  	// If we're running a full engine faking, accept any input as valid
   126  	if ubqhash.config.PowMode == ModeFullFake || len(headers) == 0 {
   127  		abort, results := make(chan struct{}), make(chan error, len(headers))
   128  		for i := 0; i < len(headers); i++ {
   129  			results <- nil
   130  		}
   131  		return abort, results
   132  	}
   133  
   134  	// Spawn as many workers as allowed threads
   135  	workers := runtime.GOMAXPROCS(0)
   136  	if len(headers) < workers {
   137  		workers = len(headers)
   138  	}
   139  
   140  	// Create a task channel and spawn the verifiers
   141  	var (
   142  		inputs = make(chan int)
   143  		done   = make(chan int, workers)
   144  		errors = make([]error, len(headers))
   145  		abort  = make(chan struct{})
   146  	)
   147  	for i := 0; i < workers; i++ {
   148  		go func() {
   149  			for index := range inputs {
   150  				errors[index] = ubqhash.verifyHeaderWorker(chain, headers, seals, index)
   151  				done <- index
   152  			}
   153  		}()
   154  	}
   155  
   156  	errorsOut := make(chan error, len(headers))
   157  	go func() {
   158  		defer close(inputs)
   159  		var (
   160  			in, out = 0, 0
   161  			checked = make([]bool, len(headers))
   162  			inputs  = inputs
   163  		)
   164  		for {
   165  			select {
   166  			case inputs <- in:
   167  				if in++; in == len(headers) {
   168  					// Reached end of headers. Stop sending to workers.
   169  					inputs = nil
   170  				}
   171  			case index := <-done:
   172  				for checked[index] = true; checked[out]; out++ {
   173  					errorsOut <- errors[out]
   174  					if out == len(headers)-1 {
   175  						return
   176  					}
   177  				}
   178  			case <-abort:
   179  				return
   180  			}
   181  		}
   182  	}()
   183  	return abort, errorsOut
   184  }
   185  
   186  func (ubqhash *Ubqhash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error {
   187  	var parent *types.Header
   188  	if index == 0 {
   189  		parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
   190  	} else if headers[index-1].Hash() == headers[index].ParentHash {
   191  		parent = headers[index-1]
   192  	}
   193  	if parent == nil {
   194  		return consensus.ErrUnknownAncestor
   195  	}
   196  	if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil {
   197  		return nil // known block
   198  	}
   199  	return ubqhash.verifyHeader(chain, headers[index], parent, false, seals[index])
   200  }
   201  
   202  // VerifyUncles verifies that the given block's uncles conform to the consensus
   203  // rules of the stock Ethereum ubqhash engine.
   204  func (ubqhash *Ubqhash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
   205  	// If we're running a full engine faking, accept any input as valid
   206  	if ubqhash.config.PowMode == ModeFullFake {
   207  		return nil
   208  	}
   209  	// Verify that there are at most 2 uncles included in this block
   210  	if len(block.Uncles()) > maxUncles {
   211  		return errTooManyUncles
   212  	}
   213  	// Gather the set of past uncles and ancestors
   214  	uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header)
   215  
   216  	number, parent := block.NumberU64()-1, block.ParentHash()
   217  	for i := 0; i < 7; i++ {
   218  		ancestor := chain.GetBlock(parent, number)
   219  		if ancestor == nil {
   220  			break
   221  		}
   222  		ancestors[ancestor.Hash()] = ancestor.Header()
   223  		for _, uncle := range ancestor.Uncles() {
   224  			uncles.Add(uncle.Hash())
   225  		}
   226  		parent, number = ancestor.ParentHash(), number-1
   227  	}
   228  	ancestors[block.Hash()] = block.Header()
   229  	uncles.Add(block.Hash())
   230  
   231  	// Verify each of the uncles that it's recent, but not an ancestor
   232  	for _, uncle := range block.Uncles() {
   233  		// Make sure every uncle is rewarded only once
   234  		hash := uncle.Hash()
   235  		if uncles.Contains(hash) {
   236  			return errDuplicateUncle
   237  		}
   238  		uncles.Add(hash)
   239  
   240  		// Make sure the uncle has a valid ancestry
   241  		if ancestors[hash] != nil {
   242  			return errUncleIsAncestor
   243  		}
   244  		if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() {
   245  			return errDanglingUncle
   246  		}
   247  		if err := ubqhash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
   248  			return err
   249  		}
   250  	}
   251  	return nil
   252  }
   253  
   254  // verifyHeader checks whether a header conforms to the consensus rules of the
   255  // stock Ethereum ubqhash engine.
   256  // See YP section 4.3.4. "Block Header Validity"
   257  func (ubqhash *Ubqhash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error {
   258  	// Ensure that the header's extra-data section is of a reasonable size
   259  	if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
   260  		return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
   261  	}
   262  	// Verify the header's timestamp
   263  	if !uncle {
   264  		if header.Time > uint64(time.Now().Add(allowedFutureBlockTime).Unix()) {
   265  			return consensus.ErrFutureBlock
   266  		}
   267  	}
   268  	if header.Time <= parent.Time {
   269  		return errZeroBlockTime
   270  	}
   271  	// Verify the block's difficulty based in it's timestamp and parent's difficulty
   272  	expected := ubqhash.CalcDifficulty(chain, header.Time, parent)
   273  
   274  	if expected.Cmp(header.Difficulty) != 0 {
   275  		return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
   276  	}
   277  	// Verify that the gas limit is <= 2^63-1
   278  	cap := uint64(0x7fffffffffffffff)
   279  	if header.GasLimit > cap {
   280  		return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
   281  	}
   282  	// Verify that the gasUsed is <= gasLimit
   283  	if header.GasUsed > header.GasLimit {
   284  		return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
   285  	}
   286  
   287  	// Verify that the gas limit remains within allowed bounds
   288  	diff := int64(parent.GasLimit) - int64(header.GasLimit)
   289  	if diff < 0 {
   290  		diff *= -1
   291  	}
   292  	limit := parent.GasLimit / params.GasLimitBoundDivisor
   293  
   294  	if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
   295  		return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
   296  	}
   297  	// Verify that the block number is parent's +1
   298  	if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
   299  		return consensus.ErrInvalidNumber
   300  	}
   301  	// Verify the engine specific seal securing the block
   302  	if seal {
   303  		if err := ubqhash.VerifySeal(chain, header); err != nil {
   304  			return err
   305  		}
   306  	}
   307  	// If all checks passed, validate any special fields for hard forks
   308  	if err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil {
   309  		return err
   310  	}
   311  	return nil
   312  }
   313  
   314  // Difficulty timespans
   315  func averagingWindowTimespan(config *diffConfig) *big.Int {
   316  	x := new(big.Int)
   317  	return x.Mul(config.AveragingWindow, big88)
   318  }
   319  
   320  func minActualTimespan(config *diffConfig, dampen bool) *big.Int {
   321  	x := new(big.Int)
   322  	y := new(big.Int)
   323  	z := new(big.Int)
   324  	if dampen {
   325  		x.Sub(config.Factor, config.Dampen)
   326  		y.Mul(averagingWindowTimespan(config), x)
   327  		z.Div(y, config.Factor)
   328  	} else {
   329  		x.Sub(config.Factor, config.MaxAdjustUp)
   330  		y.Mul(averagingWindowTimespan(config), x)
   331  		z.Div(y, config.Factor)
   332  	}
   333  	return z
   334  }
   335  
   336  func maxActualTimespan(config *diffConfig, dampen bool) *big.Int {
   337  	x := new(big.Int)
   338  	y := new(big.Int)
   339  	z := new(big.Int)
   340  	if dampen {
   341  		x.Add(config.Factor, config.Dampen)
   342  		y.Mul(averagingWindowTimespan(config), x)
   343  		z.Div(y, config.Factor)
   344  	} else {
   345  		x.Add(config.Factor, config.MaxAdjustDown)
   346  		y.Mul(averagingWindowTimespan(config), x)
   347  		z.Div(y, config.Factor)
   348  	}
   349  	return z
   350  }
   351  
   352  // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
   353  // that a new block should have when created at time given the parent block's time
   354  // and difficulty.
   355  func (ubqhash *Ubqhash) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   356  	return CalcDifficulty(chain, time, parent)
   357  }
   358  
   359  // CalcDifficulty determines which difficulty algorithm to use for calculating a new block
   360  func CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   361  	parentTime := parent.Time
   362  	parentNumber := parent.Number
   363  	parentDiff := parent.Difficulty
   364  
   365  	config := chain.Config()
   366  	ubqhashConfig := config.Ubqhash
   367  
   368  	if parentNumber.Cmp(ubqhashConfig.FluxBlock) < 0 {
   369  		if parentNumber.Cmp(ubqhashConfig.DigishieldModBlock) < 0 {
   370  			// Original DigishieldV3
   371  			return calcDifficultyDigishieldV3(chain, parentNumber, parentDiff, parent, digishieldV3Config)
   372  		}
   373  		// Modified DigishieldV3
   374  		return calcDifficultyDigishieldV3(chain, parentNumber, parentDiff, parent, digishieldV3ModConfig)
   375  	}
   376  	// Flux
   377  	return calcDifficultyFlux(chain, big.NewInt(int64(time)), big.NewInt(int64(parentTime)), parentNumber, parentDiff, parent)
   378  }
   379  
   380  // calcDifficultyDigishieldV3 is the original difficulty adjustment algorithm.
   381  // It returns the difficulty that a new block should have when created at time
   382  // given the parent block's time and difficulty.
   383  // Based on Digibyte's Digishield v3 retargeting
   384  func calcDifficultyDigishieldV3(chain consensus.ChainReader, parentNumber, parentDiff *big.Int, parent *types.Header, digishield *diffConfig) *big.Int {
   385  	// holds intermediate values to make the algo easier to read & audit
   386  	x := new(big.Int)
   387  	nFirstBlock := new(big.Int)
   388  	nFirstBlock.Sub(parentNumber, digishield.AveragingWindow)
   389  
   390  	log.Debug(fmt.Sprintf("CalcDifficulty parentNumber: %v parentDiff: %v", parentNumber, parentDiff))
   391  
   392  	// Check we have enough blocks
   393  	if parentNumber.Cmp(digishield.AveragingWindow) < 1 {
   394  		log.Debug(fmt.Sprintf("CalcDifficulty: parentNumber(%+x) < digishieldV3Config.AveragingWindow(%+x)", parentNumber, digishield.AveragingWindow))
   395  		x.Set(parentDiff)
   396  		return x
   397  	}
   398  
   399  	// Limit adjustment step
   400  	// Use medians to prevent time-warp attacks
   401  	nLastBlockTime := chain.CalcPastMedianTime(parentNumber.Uint64(), parent)
   402  	nFirstBlockTime := chain.CalcPastMedianTime(nFirstBlock.Uint64(), parent)
   403  	nActualTimespan := new(big.Int)
   404  	nActualTimespan.Sub(nLastBlockTime, nFirstBlockTime)
   405  	log.Debug(fmt.Sprintf("CalcDifficulty nActualTimespan = %v before dampening", nActualTimespan))
   406  
   407  	y := new(big.Int)
   408  	y.Sub(nActualTimespan, averagingWindowTimespan(digishield))
   409  	y.Div(y, big.NewInt(4))
   410  	nActualTimespan.Add(y, averagingWindowTimespan(digishield))
   411  	log.Debug(fmt.Sprintf("CalcDifficulty nActualTimespan = %v before bounds", nActualTimespan))
   412  
   413  	if nActualTimespan.Cmp(minActualTimespan(digishield, false)) < 0 {
   414  		nActualTimespan.Set(minActualTimespan(digishield, false))
   415  		log.Debug("CalcDifficulty Minimum Timespan set")
   416  	} else if nActualTimespan.Cmp(maxActualTimespan(digishield, false)) > 0 {
   417  		nActualTimespan.Set(maxActualTimespan(digishield, false))
   418  		log.Debug("CalcDifficulty Maximum Timespan set")
   419  	}
   420  
   421  	log.Debug(fmt.Sprintf("CalcDifficulty nActualTimespan = %v final\n", nActualTimespan))
   422  
   423  	// Retarget
   424  	x.Mul(parentDiff, averagingWindowTimespan(digishield))
   425  	log.Debug(fmt.Sprintf("CalcDifficulty parentDiff * AveragingWindowTimespan: %v", x))
   426  
   427  	x.Div(x, nActualTimespan)
   428  	log.Debug(fmt.Sprintf("CalcDifficulty x / nActualTimespan: %v", x))
   429  
   430  	if x.Cmp(params.MinimumDifficulty) < 0 {
   431  		x.Set(params.MinimumDifficulty)
   432  	}
   433  
   434  	return x
   435  }
   436  
   437  func calcDifficultyFlux(chain consensus.ChainReader, time, parentTime, parentNumber, parentDiff *big.Int, parent *types.Header) *big.Int {
   438  	x := new(big.Int)
   439  	nFirstBlock := new(big.Int)
   440  	nFirstBlock.Sub(parentNumber, fluxConfig.AveragingWindow)
   441  
   442  	// Check we have enough blocks
   443  	if parentNumber.Cmp(fluxConfig.AveragingWindow) < 1 {
   444  		log.Debug(fmt.Sprintf("CalcDifficulty: parentNumber(%+x) < fluxConfig.AveragingWindow(%+x)", parentNumber, fluxConfig.AveragingWindow))
   445  		x.Set(parentDiff)
   446  		return x
   447  	}
   448  
   449  	diffTime := new(big.Int)
   450  	diffTime.Sub(time, parentTime)
   451  
   452  	nLastBlockTime := chain.CalcPastMedianTime(parentNumber.Uint64(), parent)
   453  	nFirstBlockTime := chain.CalcPastMedianTime(nFirstBlock.Uint64(), parent)
   454  	nActualTimespan := new(big.Int)
   455  	nActualTimespan.Sub(nLastBlockTime, nFirstBlockTime)
   456  
   457  	y := new(big.Int)
   458  	y.Sub(nActualTimespan, averagingWindowTimespan(fluxConfig))
   459  	y.Div(y, big.NewInt(4))
   460  	nActualTimespan.Add(y, averagingWindowTimespan(fluxConfig))
   461  
   462  	if nActualTimespan.Cmp(minActualTimespan(fluxConfig, false)) < 0 {
   463  		doubleBig88 := new(big.Int)
   464  		doubleBig88.Mul(big88, big.NewInt(2))
   465  		if diffTime.Cmp(doubleBig88) > 0 {
   466  			nActualTimespan.Set(minActualTimespan(fluxConfig, true))
   467  		} else {
   468  			nActualTimespan.Set(minActualTimespan(fluxConfig, false))
   469  		}
   470  	} else if nActualTimespan.Cmp(maxActualTimespan(fluxConfig, false)) > 0 {
   471  		halfBig88 := new(big.Int)
   472  		halfBig88.Div(big88, big.NewInt(2))
   473  		if diffTime.Cmp(halfBig88) < 0 {
   474  			nActualTimespan.Set(maxActualTimespan(fluxConfig, true))
   475  		} else {
   476  			nActualTimespan.Set(maxActualTimespan(fluxConfig, false))
   477  		}
   478  	}
   479  
   480  	x.Mul(parentDiff, averagingWindowTimespan(fluxConfig))
   481  	x.Div(x, nActualTimespan)
   482  
   483  	if x.Cmp(params.MinimumDifficulty) < 0 {
   484  		x.Set(params.MinimumDifficulty)
   485  	}
   486  
   487  	return x
   488  }
   489  
   490  // VerifySeal implements consensus.Engine, checking whether the given block satisfies
   491  // the PoW difficulty requirements.
   492  func (ubqhash *Ubqhash) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   493  	return ubqhash.verifySeal(chain, header, false)
   494  }
   495  
   496  // verifySeal checks whether a block satisfies the PoW difficulty requirements,
   497  // either using the usual ethash cache for it, or alternatively using a full DAG
   498  // to make remote mining fast.
   499  func (ubqhash *Ubqhash) verifySeal(chain consensus.ChainReader, header *types.Header, fulldag bool) error {
   500  	// If we're running a fake PoW, accept any seal as valid
   501  	if ubqhash.config.PowMode == ModeFake || ubqhash.config.PowMode == ModeFullFake {
   502  		time.Sleep(ubqhash.fakeDelay)
   503  		if ubqhash.fakeFail == header.Number.Uint64() {
   504  			return errInvalidPoW
   505  		}
   506  		return nil
   507  	}
   508  	// If we're running a shared PoW, delegate verification to it
   509  	if ubqhash.shared != nil {
   510  		return ubqhash.shared.verifySeal(chain, header, fulldag)
   511  	}
   512  	// Ensure that we have a valid difficulty for the block
   513  	if header.Difficulty.Sign() <= 0 {
   514  		return errInvalidDifficulty
   515  	}
   516  	// Recompute the digest and PoW values
   517  	number := header.Number.Uint64()
   518  
   519  	var (
   520  		digest []byte
   521  		result []byte
   522  	)
   523  	// If fast-but-heavy PoW verification was requested, use an ethash dataset
   524  	if fulldag {
   525  		dataset := ubqhash.dataset(number, true)
   526  		if dataset.generated() {
   527  			digest, result = hashimotoFull(dataset.dataset, ubqhash.SealHash(header).Bytes(), header.Nonce.Uint64())
   528  
   529  			// Datasets are unmapped in a finalizer. Ensure that the dataset stays alive
   530  			// until after the call to hashimotoFull so it's not unmapped while being used.
   531  			runtime.KeepAlive(dataset)
   532  		} else {
   533  			// Dataset not yet generated, don't hang, use a cache instead
   534  			fulldag = false
   535  		}
   536  	}
   537  	// If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache
   538  	if !fulldag {
   539  		cache := ubqhash.cache(number)
   540  
   541  		size := datasetSize(number)
   542  		if ubqhash.config.PowMode == ModeTest {
   543  			size = 32 * 1024
   544  		}
   545  		digest, result = hashimotoLight(size, cache.cache, ubqhash.SealHash(header).Bytes(), header.Nonce.Uint64())
   546  
   547  		// Caches are unmapped in a finalizer. Ensure that the cache stays alive
   548  		// until after the call to hashimotoLight so it's not unmapped while being used.
   549  		runtime.KeepAlive(cache)
   550  	}
   551  	// Verify the calculated values against the ones provided in the header
   552  	if !bytes.Equal(header.MixDigest[:], digest) {
   553  		return errInvalidMixDigest
   554  	}
   555  	target := new(big.Int).Div(two256, header.Difficulty)
   556  	if new(big.Int).SetBytes(result).Cmp(target) > 0 {
   557  		return errInvalidPoW
   558  	}
   559  	return nil
   560  }
   561  
   562  // Prepare implements consensus.Engine, initializing the difficulty field of a
   563  // header to conform to the ubqhash protocol. The changes are done inline.
   564  func (ubqhash *Ubqhash) Prepare(chain consensus.ChainReader, header *types.Header) error {
   565  	parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
   566  	if parent == nil {
   567  		return consensus.ErrUnknownAncestor
   568  	}
   569  	header.Difficulty = CalcDifficulty(chain, header.Time, parent)
   570  
   571  	return nil
   572  }
   573  
   574  // Finalize implements consensus.Engine, accumulating the block and uncle rewards,
   575  // setting the final state and assembling the block.
   576  func (ubqhash *Ubqhash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
   577  	// Accumulate any block and uncle rewards and commit the final state root
   578  	accumulateRewards(chain.Config(), state, header, uncles)
   579  	header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   580  
   581  	// Header seems complete, assemble into a block and return
   582  	return types.NewBlock(header, txs, uncles, receipts), nil
   583  }
   584  
   585  // Some weird constants to avoid constant memory allocs for them.
   586  var (
   587  	big2  = big.NewInt(2)
   588  	big32 = big.NewInt(32)
   589  )
   590  
   591  // SealHash returns the hash of a block prior to it being sealed.
   592  func (ubqhash *Ubqhash) SealHash(header *types.Header) (hash common.Hash) {
   593  	hasher := sha3.NewLegacyKeccak256()
   594  
   595  	rlp.Encode(hasher, []interface{}{
   596  		header.ParentHash,
   597  		header.UncleHash,
   598  		header.Coinbase,
   599  		header.Root,
   600  		header.TxHash,
   601  		header.ReceiptHash,
   602  		header.Bloom,
   603  		header.Difficulty,
   604  		header.Number,
   605  		header.GasLimit,
   606  		header.GasUsed,
   607  		header.Time,
   608  		header.Extra,
   609  	})
   610  	hasher.Sum(hash[:0])
   611  	return hash
   612  }
   613  
   614  // CalcBaseBlockReward calculates the base block reward as per the ubiq monetary policy.
   615  func CalcBaseBlockReward(config *params.UbqhashConfig, height *big.Int) (*big.Int, *big.Int) {
   616  	reward := new(big.Int)
   617  
   618  	for _, step := range config.MonetaryPolicy {
   619  		if height.Cmp(step.Block) > 0 {
   620  			reward = new(big.Int).Set(step.Reward)
   621  		} else {
   622  			break
   623  		}
   624  	}
   625  
   626  	return new(big.Int).Set(config.MonetaryPolicy[0].Reward), reward
   627  }
   628  
   629  // CalcUncleBlockReward calculates the uncle miner reward based on depth.
   630  func CalcUncleBlockReward(config *params.ChainConfig, blockHeight *big.Int, uncleHeight *big.Int, blockReward *big.Int) *big.Int {
   631  	reward := new(big.Int)
   632  	// calculate reward based on depth
   633  	reward.Add(uncleHeight, big2)
   634  	reward.Sub(reward, blockHeight)
   635  	reward.Mul(reward, blockReward)
   636  	reward.Div(reward, big2)
   637  
   638  	// negative uncle reward fix. (activates along-side EIP158)
   639  	if config.IsEIP158(blockHeight) && reward.Cmp(big.NewInt(0)) < 0 {
   640  		reward = big.NewInt(0)
   641  	}
   642  	return reward
   643  }
   644  
   645  // AccumulateRewards credits the coinbase of the given block with the mining
   646  // reward. The total reward consists of the static block reward and rewards for
   647  // included uncles. The coinbase of each uncle block is also rewarded.
   648  func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
   649  	// block reward (miner)
   650  	initialReward, currentReward := CalcBaseBlockReward(config.Ubqhash, header.Number)
   651  
   652  	// Uncle reward step down fix. (activates along-side byzantium)
   653  	ufixReward := initialReward
   654  	if config.IsByzantium(header.Number) {
   655  		ufixReward = currentReward
   656  	}
   657  
   658  	for _, uncle := range uncles {
   659  		// uncle block miner reward (depth === 1 ? baseBlockReward * 0.5 : 0)
   660  		uncleReward := CalcUncleBlockReward(config, header.Number, uncle.Number, ufixReward)
   661  		// update uncle miner balance
   662  		state.AddBalance(uncle.Coinbase, uncleReward)
   663  		// include uncle bonus reward (baseBlockReward/32)
   664  		uncleReward.Div(ufixReward, big32)
   665  		currentReward.Add(currentReward, uncleReward)
   666  	}
   667  	// update block miner balance
   668  	state.AddBalance(header.Coinbase, currentReward)
   669  }