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