decred.org/dcrwallet/v3@v3.1.0/wallet/difficulty.go (about)

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Copyright (c) 2015-2023 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package wallet
     7  
     8  // This code was copied from dcrd/blockchain/difficulty.go and modified for
     9  // dcrwallet's header storage.
    10  
    11  import (
    12  	"context"
    13  	"math/big"
    14  	"time"
    15  
    16  	"decred.org/dcrwallet/v3/deployments"
    17  	"decred.org/dcrwallet/v3/errors"
    18  	"decred.org/dcrwallet/v3/wallet/walletdb"
    19  	blockchain "github.com/decred/dcrd/blockchain/standalone/v2"
    20  	"github.com/decred/dcrd/chaincfg/chainhash"
    21  	"github.com/decred/dcrd/chaincfg/v3"
    22  	"github.com/decred/dcrd/dcrutil/v4"
    23  	"github.com/decred/dcrd/wire"
    24  )
    25  
    26  func (w *Wallet) isTestNet3() bool {
    27  	return w.chainParams.Net == wire.TestNet3
    28  }
    29  
    30  const testNet3MaxDiffActivationHeight = 962928
    31  
    32  var (
    33  	// bigZero is 0 represented as a big.Int.  It is defined here to avoid
    34  	// the overhead of creating it multiple times.
    35  	bigZero = big.NewInt(0)
    36  )
    37  
    38  // findPrevTestNetDifficulty returns the difficulty of the previous block which
    39  // did not have the special testnet minimum difficulty rule applied.
    40  func (w *Wallet) findPrevTestNetDifficulty(dbtx walletdb.ReadTx, h *wire.BlockHeader, chain []*BlockNode) (uint32, error) {
    41  	// Search backwards through the chain for the last block without
    42  	// the special rule applied.
    43  	blocksPerRetarget := w.chainParams.WorkDiffWindowSize * w.chainParams.WorkDiffWindows
    44  	for int64(h.Height)%blocksPerRetarget != 0 && h.Bits == w.chainParams.PowLimitBits {
    45  		if h.PrevBlock == (chainhash.Hash{}) {
    46  			h = nil
    47  			break
    48  		}
    49  
    50  		if len(chain) > 0 && int32(h.Height)-int32(chain[0].Header.Height) > 0 {
    51  			h = chain[h.Height-chain[0].Header.Height-1].Header
    52  		} else {
    53  			var err error
    54  			h, err = w.txStore.GetBlockHeader(dbtx, &h.PrevBlock)
    55  			if err != nil {
    56  				return 0, err
    57  			}
    58  		}
    59  	}
    60  
    61  	// Return the found difficulty or the minimum difficulty if no
    62  	// appropriate block was found.
    63  	lastBits := w.chainParams.PowLimitBits
    64  	if h != nil {
    65  		lastBits = h.Bits
    66  	}
    67  	return lastBits, nil
    68  }
    69  
    70  // calcNextBlake256Diff calculates the required difficulty for the block AFTER
    71  // the passed header based on the difficulty retarget rules for the blake256
    72  // hash algorithm used at Decred launch.
    73  func (w *Wallet) calcNextBlake256Diff(dbtx walletdb.ReadTx, header *wire.BlockHeader,
    74  	chain []*BlockNode, newBlockTime time.Time) (uint32, error) {
    75  
    76  	// Get the old difficulty; if we aren't at a block height where it changes,
    77  	// just return this.
    78  	oldDiff := header.Bits
    79  	oldDiffBig := blockchain.CompactToBig(header.Bits)
    80  
    81  	// We're not at a retarget point, return the oldDiff.
    82  	params := w.chainParams
    83  	nextHeight := int64(header.Height) + 1
    84  	if nextHeight%params.WorkDiffWindowSize != 0 {
    85  		// For networks that support it, allow special reduction of the
    86  		// required difficulty once too much time has elapsed without
    87  		// mining a block.
    88  		//
    89  		// Note that this behavior is deprecated and thus is only supported on
    90  		// testnet v3 prior to the max diff activation height.  It will be
    91  		// removed in future version of testnet.
    92  		if params.ReduceMinDifficulty && (!w.isTestNet3() || nextHeight <
    93  			testNet3MaxDiffActivationHeight) {
    94  
    95  			// Return minimum difficulty when more than the desired
    96  			// amount of time has elapsed without mining a block.
    97  			reductionTime := int64(params.MinDiffReductionTime /
    98  				time.Second)
    99  			allowMinTime := header.Timestamp.Unix() + reductionTime
   100  			if newBlockTime.Unix() > allowMinTime {
   101  				return params.PowLimitBits, nil
   102  			}
   103  
   104  			// The block was mined within the desired timeframe, so
   105  			// return the difficulty for the last block which did
   106  			// not have the special minimum difficulty rule applied.
   107  			return w.findPrevTestNetDifficulty(dbtx, header, chain)
   108  		}
   109  
   110  		return oldDiff, nil
   111  	}
   112  
   113  	// Declare some useful variables.
   114  	RAFBig := big.NewInt(w.chainParams.RetargetAdjustmentFactor)
   115  	nextDiffBigMin := blockchain.CompactToBig(header.Bits)
   116  	nextDiffBigMin.Div(nextDiffBigMin, RAFBig)
   117  	nextDiffBigMax := blockchain.CompactToBig(header.Bits)
   118  	nextDiffBigMax.Mul(nextDiffBigMax, RAFBig)
   119  
   120  	alpha := params.WorkDiffAlpha
   121  
   122  	// Number of nodes to traverse while calculating difficulty.
   123  	nodesToTraverse := (params.WorkDiffWindowSize * params.WorkDiffWindows)
   124  
   125  	// Initialize bigInt slice for the percentage changes for each window period
   126  	// above or below the target.
   127  	windowChanges := make([]*big.Int, params.WorkDiffWindows)
   128  
   129  	// Regress through all of the previous blocks and store the percent changes
   130  	// per window period; use bigInts to emulate 64.32 bit fixed point.
   131  	var olderTime, windowPeriod int64
   132  	var weights uint64
   133  	oldHeader := header
   134  	recentTime := header.Timestamp.Unix()
   135  
   136  	for i := int64(0); ; i++ {
   137  		// Store and reset after reaching the end of every window period.
   138  		if i%params.WorkDiffWindowSize == 0 && i != 0 {
   139  			olderTime = oldHeader.Timestamp.Unix()
   140  			timeDifference := recentTime - olderTime
   141  
   142  			// Just assume we're at the target (no change) if we've
   143  			// gone all the way back to the genesis block.
   144  			if oldHeader.Height == 0 {
   145  				timeDifference = int64(params.TargetTimespan /
   146  					time.Second)
   147  			}
   148  
   149  			timeDifBig := big.NewInt(timeDifference)
   150  			timeDifBig.Lsh(timeDifBig, 32) // Add padding
   151  			targetTemp := big.NewInt(int64(params.TargetTimespan /
   152  				time.Second))
   153  
   154  			windowAdjusted := targetTemp.Div(timeDifBig, targetTemp)
   155  
   156  			// Weight it exponentially. Be aware that this could at some point
   157  			// overflow if alpha or the number of blocks used is really large.
   158  			windowAdjusted = windowAdjusted.Lsh(windowAdjusted,
   159  				uint((params.WorkDiffWindows-windowPeriod)*alpha))
   160  
   161  			// Sum up all the different weights incrementally.
   162  			weights += 1 << uint64((params.WorkDiffWindows-windowPeriod)*
   163  				alpha)
   164  
   165  			// Store it in the slice.
   166  			windowChanges[windowPeriod] = windowAdjusted
   167  
   168  			windowPeriod++
   169  
   170  			recentTime = olderTime
   171  		}
   172  
   173  		if i == nodesToTraverse {
   174  			break // Exit for loop when we hit the end.
   175  		}
   176  
   177  		// Get the previous node while staying at the genesis block as needed.
   178  		// Query the header from the provided chain instead of database if
   179  		// present.  The parent of chain[0] is guaranteed to be in stored in the
   180  		// database.
   181  		if oldHeader.Height != 0 {
   182  			if len(chain) > 0 && int32(oldHeader.Height)-int32(chain[0].Header.Height) > 0 {
   183  				oldHeader = chain[oldHeader.Height-chain[0].Header.Height-1].Header
   184  			} else {
   185  				var err error
   186  				oldHeader, err = w.txStore.GetBlockHeader(dbtx, &oldHeader.PrevBlock)
   187  				if err != nil {
   188  					return 0, err
   189  				}
   190  			}
   191  		}
   192  	}
   193  
   194  	// Sum up the weighted window periods.
   195  	weightedSum := big.NewInt(0)
   196  	for i := int64(0); i < params.WorkDiffWindows; i++ {
   197  		weightedSum.Add(weightedSum, windowChanges[i])
   198  	}
   199  
   200  	// Divide by the sum of all weights.
   201  	weightsBig := big.NewInt(int64(weights))
   202  	weightedSumDiv := weightedSum.Div(weightedSum, weightsBig)
   203  
   204  	// Multiply by the old diff.
   205  	nextDiffBig := weightedSumDiv.Mul(weightedSumDiv, oldDiffBig)
   206  
   207  	// Right shift to restore the original padding (restore non-fixed point).
   208  	nextDiffBig = nextDiffBig.Rsh(nextDiffBig, 32)
   209  
   210  	// Check to see if we're over the limits for the maximum allowable retarget;
   211  	// if we are, return the maximum or minimum except in the case that oldDiff
   212  	// is zero.
   213  	if oldDiffBig.Cmp(bigZero) == 0 { // This should never really happen,
   214  		nextDiffBig.Set(nextDiffBig) // but in case it does...
   215  	} else if nextDiffBig.Cmp(bigZero) == 0 {
   216  		nextDiffBig.Set(params.PowLimit)
   217  	} else if nextDiffBig.Cmp(nextDiffBigMax) == 1 {
   218  		nextDiffBig.Set(nextDiffBigMax)
   219  	} else if nextDiffBig.Cmp(nextDiffBigMin) == -1 {
   220  		nextDiffBig.Set(nextDiffBigMin)
   221  	}
   222  
   223  	// Prevent the difficulty from going lower than the minimum allowed
   224  	// difficulty.
   225  	//
   226  	// Larger numbers result in a lower difficulty, so imposing a minimum
   227  	// difficulty equates to limiting the maximum target value.
   228  	if nextDiffBig.Cmp(params.PowLimit) > 0 {
   229  		nextDiffBig.Set(params.PowLimit)
   230  	}
   231  
   232  	// Prevent the difficulty from going higher than a maximum allowed
   233  	// difficulty on the test network.  This is to prevent runaway difficulty on
   234  	// testnet by ASICs and GPUs since it's not reasonable to require
   235  	// high-powered hardware to keep the test network running smoothly.
   236  	//
   237  	// Smaller numbers result in a higher difficulty, so imposing a maximum
   238  	// difficulty equates to limiting the minimum target value.
   239  	//
   240  	// This rule is only active on the version 3 test network once the max diff
   241  	// activation height has been reached.
   242  	if w.minTestNetTarget != nil && nextDiffBig.Cmp(w.minTestNetTarget) < 0 &&
   243  		(!w.isTestNet3() || nextHeight >= testNet3MaxDiffActivationHeight) {
   244  
   245  		nextDiffBig = w.minTestNetTarget
   246  	}
   247  
   248  	// Convert the difficulty to the compact representation and return it.
   249  	nextDiffBits := blockchain.BigToCompact(nextDiffBig)
   250  	return nextDiffBits, nil
   251  }
   252  
   253  func (w *Wallet) loadCachedBlake3WorkDiffCandidateAnchor() *wire.BlockHeader {
   254  	w.cachedBlake3WorkDiffCandidateAnchorMu.Lock()
   255  	defer w.cachedBlake3WorkDiffCandidateAnchorMu.Unlock()
   256  
   257  	return w.cachedBlake3WorkDiffCandidateAnchor
   258  }
   259  
   260  func (w *Wallet) storeCachedBlake3WorkDiffCandidateAnchor(candidate *wire.BlockHeader) {
   261  	w.cachedBlake3WorkDiffCandidateAnchorMu.Lock()
   262  	defer w.cachedBlake3WorkDiffCandidateAnchorMu.Unlock()
   263  
   264  	w.cachedBlake3WorkDiffCandidateAnchor = candidate
   265  }
   266  
   267  // isBlake3PowAgendaForcedActive returns whether or not the agenda to change the
   268  // proof of work hash function to blake3, as defined in DCP0011, is forced
   269  // active by the chain parameters.
   270  func (w *Wallet) isBlake3PowAgendaForcedActive() bool {
   271  	const deploymentID = chaincfg.VoteIDBlake3Pow
   272  	deployment, ok := w.deploymentsByID[deploymentID]
   273  	if !ok {
   274  		return false
   275  	}
   276  
   277  	return deployment.ForcedChoiceID == "yes"
   278  }
   279  
   280  // calcNextBlake3DiffFromAnchor calculates the required difficulty for the block
   281  // AFTER the passed previous block node relative to the given anchor block based
   282  // on the difficulty retarget rules defined in DCP0011.
   283  //
   284  // This function is safe for concurrent access.
   285  func (w *Wallet) calcNextBlake3DiffFromAnchor(prevNode, blake3Anchor *wire.BlockHeader) uint32 {
   286  	// Calculate the time and height deltas as the difference between the
   287  	// provided block and the blake3 anchor block.
   288  	//
   289  	// Notice that if the difficulty prior to the activation point were being
   290  	// maintained, this would need to be the timestamp and height of the parent
   291  	// of the blake3 anchor block (except when the anchor is the genesis block)
   292  	// in order for the absolute calculations to exactly match the behavior of
   293  	// relative calculations.
   294  	//
   295  	// However, since the initial difficulty is reset with the agenda, no
   296  	// additional offsets are needed.
   297  	timeDelta := prevNode.Timestamp.Unix() - blake3Anchor.Timestamp.Unix()
   298  	heightDelta := int64(prevNode.Height) - int64(blake3Anchor.Height)
   299  
   300  	// Calculate the next target difficulty using the ASERT algorithm.
   301  	//
   302  	// Note that the difficulty of the anchor block is NOT used for the initial
   303  	// difficulty because the difficulty must be reset due to the change to
   304  	// blake3 for proof of work.  The initial difficulty comes from the chain
   305  	// parameters instead.
   306  	params := w.chainParams
   307  	nextDiff := blockchain.CalcASERTDiff(params.WorkDiffV2Blake3StartBits,
   308  		params.PowLimit, int64(params.TargetTimePerBlock.Seconds()), timeDelta,
   309  		heightDelta, params.WorkDiffV2HalfLifeSecs)
   310  
   311  	// Prevent the difficulty from going higher than a maximum allowed
   312  	// difficulty on the test network.  This is to prevent runaway difficulty on
   313  	// testnet by ASICs and GPUs since it's not reasonable to require
   314  	// high-powered hardware to keep the test network running smoothly.
   315  	//
   316  	// Smaller numbers result in a higher difficulty, so imposing a maximum
   317  	// difficulty equates to limiting the minimum target value.
   318  	if w.minTestNetTarget != nil && nextDiff < w.minTestNetDiffBits {
   319  		nextDiff = w.minTestNetDiffBits
   320  	}
   321  
   322  	return nextDiff
   323  }
   324  
   325  // calcWantHeight calculates the height of the final block of the previous
   326  // interval given a stake validation height, stake validation interval, and
   327  // block height.
   328  func calcWantHeight(stakeValidationHeight, interval, height int64) int64 {
   329  	// The adjusted height accounts for the fact the starting validation
   330  	// height does not necessarily start on an interval and thus the
   331  	// intervals might not be zero-based.
   332  	intervalOffset := stakeValidationHeight % interval
   333  	adjustedHeight := height - intervalOffset - 1
   334  	return (adjustedHeight - ((adjustedHeight + 1) % interval)) +
   335  		intervalOffset
   336  }
   337  
   338  // checkDifficultyPositional ensures the difficulty specified in the block
   339  // header matches the calculated difficulty based on the difficulty retarget
   340  // rules.  These checks do not, and must not, rely on having the full block data
   341  // of all ancestors available.
   342  //
   343  // This function is safe for concurrent access.
   344  func (w *Wallet) checkDifficultyPositional(dbtx walletdb.ReadTx, header *wire.BlockHeader,
   345  	prevNode *wire.BlockHeader, chain []*BlockNode) error {
   346  	// -------------------------------------------------------------------------
   347  	// The ability to determine whether or not the blake3 proof of work agenda
   348  	// is active is not possible in the general case here because that relies on
   349  	// additional context that is not available in the positional checks.
   350  	// However, it is important to check for valid bits in the positional checks
   351  	// to protect against various forms of malicious behavior.
   352  	//
   353  	// Thus, with the exception of the special cases where it is possible to
   354  	// definitively determine the agenda is active, allow valid difficulty bits
   355  	// under both difficulty algorithms while rejecting blocks that satisify
   356  	// neither here in the positional checks and allow the contextual checks
   357  	// that happen later to ensure the difficulty bits are valid specifically
   358  	// for the correct difficulty algorithm as determined by the state of the
   359  	// blake3 proof of work agenda.
   360  	// -------------------------------------------------------------------------
   361  
   362  	// Ensure the difficulty specified in the block header matches the
   363  	// calculated difficulty using the algorithm defined in DCP0011 when the
   364  	// blake3 proof of work agenda is always active.
   365  	//
   366  	// Apply special handling for networks where the agenda is always active to
   367  	// always require the initial starting difficulty for the first block and to
   368  	// treat the first block as the anchor once it has been mined.
   369  	//
   370  	// This is to done to help provide better difficulty target behavior for the
   371  	// initial blocks on such networks since the genesis block will necessarily
   372  	// have a hard-coded timestamp that will very likely be outdated by the time
   373  	// mining starts.  As a result, merely using the genesis block as the anchor
   374  	// for all blocks would likely result in a lot of the initial blocks having
   375  	// a significantly lower difficulty than desired because they would all be
   376  	// behind the ideal schedule relative to that outdated timestamp.
   377  	if w.isBlake3PowAgendaForcedActive() {
   378  		var blake3Diff uint32
   379  
   380  		// Use the initial starting difficulty for the first block.
   381  		if prevNode.Height == 0 {
   382  			blake3Diff = w.chainParams.WorkDiffV2Blake3StartBits
   383  		} else {
   384  			// Treat the first block as the anchor for all descendants of it.
   385  			anchor, err := w.ancestorHeaderAtHeight(dbtx, prevNode, chain, 1)
   386  			if err != nil {
   387  				return err
   388  			}
   389  			blake3Diff = w.calcNextBlake3DiffFromAnchor(prevNode, anchor)
   390  		}
   391  
   392  		if header.Bits != blake3Diff {
   393  			err := errors.Errorf("%w: block difficulty of %d is not the expected "+
   394  				"value of %d (difficulty algorithm: ASERT)",
   395  				blockchain.ErrUnexpectedDifficulty, header.Bits, blake3Diff)
   396  			return errors.E(errors.Consensus, err)
   397  		}
   398  
   399  		return nil
   400  	}
   401  
   402  	// Only the original difficulty algorithm needs to be checked when it is
   403  	// impossible for the blake3 proof of work agenda to be active or the block
   404  	// is not solved for blake3.
   405  	//
   406  	// Note that since the case where the blake3 proof of work agenda is always
   407  	// active is already handled above, the only remaining way for the agenda to
   408  	// be active is for it to have been voted in which requires voting to be
   409  	// possible (stake validation height), at least one interval of voting, and
   410  	// one interval of being locked in.
   411  	isSolvedBlake3 := func(header *wire.BlockHeader) bool {
   412  		powHash := header.PowHashV2()
   413  		err := blockchain.CheckProofOfWorkHash(&powHash, header.Bits)
   414  		return err == nil
   415  	}
   416  	rcai := int64(w.chainParams.RuleChangeActivationInterval)
   417  	svh := w.chainParams.StakeValidationHeight
   418  	firstPossibleActivationHeight := svh + rcai*2
   419  	minBlake3BlockVersion := uint32(10)
   420  	if w.chainParams.Net != wire.MainNet {
   421  		minBlake3BlockVersion++
   422  	}
   423  	isBlake3PossiblyActive := uint32(header.Version) >= minBlake3BlockVersion &&
   424  		int64(header.Height) >= firstPossibleActivationHeight
   425  	if !isBlake3PossiblyActive || !isSolvedBlake3(header) {
   426  		// Ensure the difficulty specified in the block header matches the
   427  		// calculated difficulty based on the previous block and difficulty
   428  		// retarget rules for the blake256 hash algorithm used at Decred launch.
   429  		blake256Diff, err := w.calcNextBlake256Diff(dbtx, prevNode, chain, header.Timestamp)
   430  		if err != nil {
   431  			return err
   432  		}
   433  		if header.Bits != blake256Diff {
   434  			err := errors.Errorf("%w: block difficulty of %d is not the expected "+
   435  				"value of %d (difficulty algorithm: EMA)",
   436  				blockchain.ErrUnexpectedDifficulty, header.Bits, blake256Diff)
   437  			return errors.E(errors.Consensus, err)
   438  		}
   439  
   440  		return nil
   441  	}
   442  
   443  	// At this point, the blake3 proof of work agenda might possibly be active
   444  	// and the block is solved using blake3, so the agenda is very likely
   445  	// active.
   446  	//
   447  	// Calculating the required difficulty once the agenda activates for the
   448  	// algorithm defined in DCP0011 requires the block prior to the activation
   449  	// of the agenda as an anchor.  However, as previously discussed, the
   450  	// additional context needed to definitively determine when the agenda
   451  	// activated is not available here in the positional checks.
   452  	//
   453  	// In light of that, the following logic uses the fact that the agenda could
   454  	// have only possibly activated at a rule change activation interval to
   455  	// iterate backwards one interval at a time through all possible candidate
   456  	// anchors until one of them results in a required difficulty that matches.
   457  	//
   458  	// In the case there is a match, the header is assumed to be valid enough to
   459  	// make it through the positional checks.
   460  	//
   461  	// As an additional optimization to avoid a bunch of extra work during the
   462  	// initial header sync, a candidate anchor that results in a matching
   463  	// required difficulty is cached and tried first on subsequent descendant
   464  	// headers since it is very likely to be the correct one.
   465  	cachedCandidate := w.loadCachedBlake3WorkDiffCandidateAnchor()
   466  	if cachedCandidate != nil {
   467  		isAncestor, err := w.isAncestorOf(dbtx, cachedCandidate, prevNode, chain)
   468  		if err != nil {
   469  			return err
   470  		}
   471  		if isAncestor {
   472  			blake3Diff := w.calcNextBlake3DiffFromAnchor(prevNode, cachedCandidate)
   473  			if header.Bits == blake3Diff {
   474  				return nil
   475  			}
   476  		}
   477  	}
   478  
   479  	// Iterate backwards through all possible anchor candidates which
   480  	// consist of the final blocks of previous rule change activation
   481  	// intervals so long as the block also has a version that is at least
   482  	// the minimum version that is enforced before voting on the agenda
   483  	// could have even started and the agenda could still possibly be
   484  	// active.
   485  	finalNodeHeight := calcWantHeight(svh, rcai, int64(header.Height))
   486  	candidate, err := w.ancestorHeaderAtHeight(dbtx, prevNode, chain, int32(finalNodeHeight))
   487  	if err != nil {
   488  		return err
   489  	}
   490  	for candidate != nil &&
   491  		uint32(candidate.Version) >= minBlake3BlockVersion &&
   492  		int64(candidate.Height) >= firstPossibleActivationHeight-1 {
   493  
   494  		blake3Diff := w.calcNextBlake3DiffFromAnchor(prevNode, candidate)
   495  		if header.Bits == blake3Diff {
   496  			w.storeCachedBlake3WorkDiffCandidateAnchor(candidate)
   497  			return nil
   498  		}
   499  		candidate, err = w.relativeAncestor(dbtx, candidate, rcai, chain)
   500  		if err != nil {
   501  			return err
   502  		}
   503  	}
   504  
   505  	// At this point, none of the possible difficulties for blake3 matched, so
   506  	// the agenda is very likely not actually active and therefore the only
   507  	// remaining valid option is the original difficulty algorithm.
   508  	//
   509  	// Ensure the difficulty specified in the block header matches the
   510  	// calculated difficulty based on the previous block and difficulty retarget
   511  	// rules for the blake256 hash algorithm used at Decred launch.
   512  	blake256Diff, err := w.calcNextBlake256Diff(dbtx, prevNode, chain, header.Timestamp)
   513  	if err != nil {
   514  		return err
   515  	}
   516  	if header.Bits != blake256Diff {
   517  		err := errors.Errorf("%w: block difficulty of %d is not the expected value "+
   518  			"of %d (difficulty algorithm: EMA)",
   519  			blockchain.ErrUnexpectedDifficulty, header.Bits, blake256Diff)
   520  		return errors.E(errors.Consensus, err)
   521  	}
   522  
   523  	return nil
   524  }
   525  
   526  // estimateSupply returns an estimate of the coin supply for the provided block
   527  // height.  This is primarily used in the stake difficulty algorithm and relies
   528  // on an estimate to simplify the necessary calculations.  The actual total
   529  // coin supply as of a given block height depends on many factors such as the
   530  // number of votes included in every prior block (not including all votes
   531  // reduces the subsidy) and whether or not any of the prior blocks have been
   532  // invalidated by stakeholders thereby removing the PoW subsidy for them.
   533  func estimateSupply(params *chaincfg.Params, height int64) int64 {
   534  	if height <= 0 {
   535  		return 0
   536  	}
   537  
   538  	// Estimate the supply by calculating the full block subsidy for each
   539  	// reduction interval and multiplying it the number of blocks in the
   540  	// interval then adding the subsidy produced by number of blocks in the
   541  	// current interval.
   542  	supply := params.BlockOneSubsidy()
   543  	reductions := height / params.SubsidyReductionInterval
   544  	subsidy := params.BaseSubsidy
   545  	for i := int64(0); i < reductions; i++ {
   546  		supply += params.SubsidyReductionInterval * subsidy
   547  
   548  		subsidy *= params.MulSubsidy
   549  		subsidy /= params.DivSubsidy
   550  	}
   551  	supply += (1 + height%params.SubsidyReductionInterval) * subsidy
   552  
   553  	// Blocks 0 and 1 have special subsidy amounts that have already been
   554  	// added above, so remove what their subsidies would have normally been
   555  	// which were also added above.
   556  	supply -= params.BaseSubsidy * 2
   557  
   558  	return supply
   559  }
   560  
   561  // sumPurchasedTickets returns the sum of the number of tickets purchased in the
   562  // most recent specified number of blocks from the point of view of the passed
   563  // header.
   564  func (w *Wallet) sumPurchasedTickets(dbtx walletdb.ReadTx, startHeader *wire.BlockHeader, chain []*BlockNode, numToSum int64) (int64, error) {
   565  	var numPurchased int64
   566  	for h, numTraversed := startHeader, int64(0); h != nil && numTraversed < numToSum; numTraversed++ {
   567  		numPurchased += int64(h.FreshStake)
   568  		if h.PrevBlock == (chainhash.Hash{}) {
   569  			break
   570  		}
   571  		if len(chain) > 0 && int32(h.Height)-int32(chain[0].Header.Height) > 0 {
   572  			h = chain[h.Height-chain[0].Header.Height-1].Header
   573  			continue
   574  		}
   575  		var err error
   576  		h, err = w.txStore.GetBlockHeader(dbtx, &h.PrevBlock)
   577  		if err != nil {
   578  			return 0, err
   579  		}
   580  	}
   581  
   582  	return numPurchased, nil
   583  }
   584  
   585  // calcNextStakeDiffV2 calculates the next stake difficulty for the given set
   586  // of parameters using the algorithm defined in DCP0001.
   587  //
   588  // This function contains the heart of the algorithm and thus is separated for
   589  // use in both the actual stake difficulty calculation as well as estimation.
   590  //
   591  // The caller must perform all of the necessary chain traversal in order to
   592  // get the current difficulty, previous retarget interval's pool size plus
   593  // its immature tickets, as well as the current pool size plus immature tickets.
   594  func calcNextStakeDiffV2(params *chaincfg.Params, nextHeight, curDiff, prevPoolSizeAll, curPoolSizeAll int64) int64 {
   595  	// Shorter version of various parameter for convenience.
   596  	votesPerBlock := int64(params.TicketsPerBlock)
   597  	ticketPoolSize := int64(params.TicketPoolSize)
   598  	ticketMaturity := int64(params.TicketMaturity)
   599  
   600  	// Calculate the difficulty by multiplying the old stake difficulty
   601  	// with two ratios that represent a force to counteract the relative
   602  	// change in the pool size (Fc) and a restorative force to push the pool
   603  	// size  towards the target value (Fr).
   604  	//
   605  	// Per DCP0001, the generalized equation is:
   606  	//
   607  	//   nextDiff = min(max(curDiff * Fc * Fr, Slb), Sub)
   608  	//
   609  	// The detailed form expands to:
   610  	//
   611  	//                        curPoolSizeAll      curPoolSizeAll
   612  	//   nextDiff = curDiff * ---------------  * -----------------
   613  	//                        prevPoolSizeAll    targetPoolSizeAll
   614  	//
   615  	//   Slb = w.chainParams.MinimumStakeDiff
   616  	//
   617  	//               estimatedTotalSupply
   618  	//   Sub = -------------------------------
   619  	//          targetPoolSize / votesPerBlock
   620  	//
   621  	// In order to avoid the need to perform floating point math which could
   622  	// be problematic across languages due to uncertainty in floating point
   623  	// math libs, this is further simplified to integer math as follows:
   624  	//
   625  	//                   curDiff * curPoolSizeAll^2
   626  	//   nextDiff = -----------------------------------
   627  	//              prevPoolSizeAll * targetPoolSizeAll
   628  	//
   629  	// Further, the Sub parameter must calculate the denomitor first using
   630  	// integer math.
   631  	targetPoolSizeAll := votesPerBlock * (ticketPoolSize + ticketMaturity)
   632  	curPoolSizeAllBig := big.NewInt(curPoolSizeAll)
   633  	nextDiffBig := big.NewInt(curDiff)
   634  	nextDiffBig.Mul(nextDiffBig, curPoolSizeAllBig)
   635  	nextDiffBig.Mul(nextDiffBig, curPoolSizeAllBig)
   636  	nextDiffBig.Div(nextDiffBig, big.NewInt(prevPoolSizeAll))
   637  	nextDiffBig.Div(nextDiffBig, big.NewInt(targetPoolSizeAll))
   638  
   639  	// Limit the new stake difficulty between the minimum allowed stake
   640  	// difficulty and a maximum value that is relative to the total supply.
   641  	//
   642  	// NOTE: This is intentionally using integer math to prevent any
   643  	// potential issues due to uncertainty in floating point math libs.  The
   644  	// ticketPoolSize parameter already contains the result of
   645  	// (targetPoolSize / votesPerBlock).
   646  	nextDiff := nextDiffBig.Int64()
   647  	estimatedSupply := estimateSupply(params, nextHeight)
   648  	maximumStakeDiff := estimatedSupply / ticketPoolSize
   649  	if nextDiff > maximumStakeDiff {
   650  		nextDiff = maximumStakeDiff
   651  	}
   652  	if nextDiff < params.MinimumStakeDiff {
   653  		nextDiff = params.MinimumStakeDiff
   654  	}
   655  	return nextDiff
   656  }
   657  
   658  func (w *Wallet) ancestorHeaderAtHeight(dbtx walletdb.ReadTx, h *wire.BlockHeader, chain []*BlockNode, height int32) (*wire.BlockHeader, error) {
   659  	switch {
   660  	case height == int32(h.Height):
   661  		return h, nil
   662  	case height > int32(h.Height), height < 0:
   663  		return nil, nil // dcrd's blockNode.Ancestor returns nil for child heights
   664  	}
   665  
   666  	if len(chain) > 0 && height-int32(chain[0].Header.Height) >= 0 {
   667  		return chain[height-int32(chain[0].Header.Height)].Header, nil
   668  	}
   669  
   670  	// Because the parent of chain[0] must be in the main chain, the header can
   671  	// be queried by its main chain height.
   672  	ns := dbtx.ReadBucket(wtxmgrNamespaceKey)
   673  	hash, err := w.txStore.GetMainChainBlockHashForHeight(ns, height)
   674  	if err != nil {
   675  		return nil, err
   676  	}
   677  	return w.txStore.GetBlockHeader(dbtx, &hash)
   678  }
   679  
   680  // isAncestorOf returns whether or not node is an ancestor of the provided
   681  // target node.
   682  //
   683  // Replaces dcrd's internal/blockchain func (node *blockNode).IsAncestorOf(target *blockNode).
   684  func (w *Wallet) isAncestorOf(dbtx walletdb.ReadTx, node, target *wire.BlockHeader,
   685  	chain []*BlockNode) (bool, error) {
   686  
   687  	ancestorHeader, err := w.ancestorHeaderAtHeight(dbtx, target, chain, int32(node.Height))
   688  	if err != nil {
   689  		return false, err
   690  	}
   691  	return ancestorHeader.BlockHash() == node.BlockHash(), nil
   692  }
   693  
   694  // relativeAncestor returns the ancestor block node a relative 'distance' blocks
   695  // before this node.  This is equivalent to calling Ancestor with the node's
   696  // height minus provided distance.
   697  //
   698  // Replaces dcrd's internal/blockchain func (node *blockNode) RelativeAncestor(distance int64).
   699  func (w *Wallet) relativeAncestor(dbtx walletdb.ReadTx, node *wire.BlockHeader,
   700  	distance int64, chain []*BlockNode) (*wire.BlockHeader, error) {
   701  
   702  	return w.ancestorHeaderAtHeight(dbtx, node, chain, int32(node.Height)-int32(distance))
   703  }
   704  
   705  // nextRequiredDCP0001PoSDifficulty calculates the required stake difficulty for
   706  // the block after the passed previous block node based on the algorithm defined
   707  // in DCP0001.
   708  func (w *Wallet) nextRequiredDCP0001PoSDifficulty(dbtx walletdb.ReadTx, curHeader *wire.BlockHeader, chain []*BlockNode) (dcrutil.Amount, error) {
   709  	// Stake difficulty before any tickets could possibly be purchased is
   710  	// the minimum value.
   711  	nextHeight := int64(0)
   712  	if curHeader != nil {
   713  		nextHeight = int64(curHeader.Height) + 1
   714  	}
   715  	stakeDiffStartHeight := int64(w.chainParams.CoinbaseMaturity) + 1
   716  	if nextHeight < stakeDiffStartHeight {
   717  		return dcrutil.Amount(w.chainParams.MinimumStakeDiff), nil
   718  	}
   719  
   720  	// Return the previous block's difficulty requirements if the next block
   721  	// is not at a difficulty retarget interval.
   722  	intervalSize := w.chainParams.StakeDiffWindowSize
   723  	curDiff := curHeader.SBits
   724  	if nextHeight%intervalSize != 0 {
   725  		return dcrutil.Amount(curDiff), nil
   726  	}
   727  
   728  	// Get the pool size and number of tickets that were immature at the
   729  	// previous retarget interval.
   730  	//
   731  	// NOTE: Since the stake difficulty must be calculated based on existing
   732  	// blocks, it is always calculated for the block after a given block, so
   733  	// the information for the previous retarget interval must be retrieved
   734  	// relative to the block just before it to coincide with how it was
   735  	// originally calculated.
   736  	var prevPoolSize int64
   737  	prevRetargetHeight := nextHeight - intervalSize - 1
   738  	prevRetargetHeader, err := w.ancestorHeaderAtHeight(dbtx, curHeader, chain, int32(prevRetargetHeight))
   739  	if err != nil {
   740  		return 0, err
   741  	}
   742  	if prevRetargetHeader != nil {
   743  		prevPoolSize = int64(prevRetargetHeader.PoolSize)
   744  	}
   745  	ticketMaturity := int64(w.chainParams.TicketMaturity)
   746  	prevImmatureTickets, err := w.sumPurchasedTickets(dbtx, prevRetargetHeader, chain, ticketMaturity)
   747  	if err != nil {
   748  		return 0, err
   749  	}
   750  
   751  	// Return the existing ticket price for the first few intervals to avoid
   752  	// division by zero and encourage initial pool population.
   753  	prevPoolSizeAll := prevPoolSize + prevImmatureTickets
   754  	if prevPoolSizeAll == 0 {
   755  		return dcrutil.Amount(curDiff), nil
   756  	}
   757  
   758  	// Count the number of currently immature tickets.
   759  	immatureTickets, err := w.sumPurchasedTickets(dbtx, curHeader, chain, ticketMaturity)
   760  	if err != nil {
   761  		return 0, err
   762  	}
   763  
   764  	// Calculate and return the final next required difficulty.
   765  	curPoolSizeAll := int64(curHeader.PoolSize) + immatureTickets
   766  	sdiff := calcNextStakeDiffV2(w.chainParams, nextHeight, curDiff, prevPoolSizeAll, curPoolSizeAll)
   767  	return dcrutil.Amount(sdiff), nil
   768  }
   769  
   770  // NextStakeDifficulty returns the ticket price for the next block after the
   771  // current main chain tip block.  This function only succeeds when DCP0001 is
   772  // known to be active.  As a fallback, the StakeDifficulty method of
   773  // wallet.NetworkBackend may be used to query the next ticket price from a
   774  // trusted full node.
   775  func (w *Wallet) NextStakeDifficulty(ctx context.Context) (dcrutil.Amount, error) {
   776  	const op errors.Op = "wallet.NextStakeDifficulty"
   777  	var sdiff dcrutil.Amount
   778  	err := walletdb.View(ctx, w.db, func(dbtx walletdb.ReadTx) error {
   779  		tipHash, tipHeight := w.txStore.MainChainTip(dbtx)
   780  		if !deployments.DCP0001.Active(tipHeight, w.chainParams.Net) {
   781  			return errors.E(errors.Deployment, "DCP0001 is not known to be active")
   782  		}
   783  		tipHeader, err := w.txStore.GetBlockHeader(dbtx, &tipHash)
   784  		if err != nil {
   785  			return err
   786  		}
   787  		sdiff, err = w.nextRequiredDCP0001PoSDifficulty(dbtx, tipHeader, nil)
   788  		return err
   789  	})
   790  	if err != nil {
   791  		return 0, errors.E(op, err)
   792  	}
   793  	return sdiff, nil
   794  }
   795  
   796  // NextStakeDifficultyAfterHeader returns the ticket price for the child of h.
   797  // All headers of ancestor blocks of h must be recorded by the wallet.  This
   798  // function only succeeds when DCP0001 is known to be active.
   799  func (w *Wallet) NextStakeDifficultyAfterHeader(ctx context.Context, h *wire.BlockHeader) (dcrutil.Amount, error) {
   800  	const op errors.Op = "wallet.NextStakeDifficultyAfterHeader"
   801  	if !deployments.DCP0001.Active(int32(h.Height), w.chainParams.Net) {
   802  		return 0, errors.E(op, errors.Deployment, "DCP0001 is not known to be active")
   803  	}
   804  	var sdiff dcrutil.Amount
   805  	err := walletdb.View(ctx, w.db, func(dbtx walletdb.ReadTx) error {
   806  		var err error
   807  		sdiff, err = w.nextRequiredDCP0001PoSDifficulty(dbtx, h, nil)
   808  		return err
   809  	})
   810  	if err != nil {
   811  		return 0, errors.E(op, err)
   812  	}
   813  	return sdiff, nil
   814  }
   815  
   816  // ValidateHeaderChainDifficulties validates the PoW and PoS difficulties of all
   817  // blocks in chain[idx:].  The parent of chain[0] must be recorded as wallet
   818  // main chain block.  If a consensus violation is caught, a subslice of chain
   819  // beginning with the invalid block is returned.
   820  func (w *Wallet) ValidateHeaderChainDifficulties(ctx context.Context, chain []*BlockNode, idx int) ([]*BlockNode, error) {
   821  	var invalid []*BlockNode
   822  	err := walletdb.View(ctx, w.db, func(dbtx walletdb.ReadTx) error {
   823  		var err error
   824  		invalid, err = w.validateHeaderChainDifficulties(dbtx, chain, idx)
   825  		return err
   826  	})
   827  	return invalid, err
   828  }
   829  
   830  func (w *Wallet) validateHeaderChainDifficulties(dbtx walletdb.ReadTx, chain []*BlockNode, idx int) ([]*BlockNode, error) {
   831  	const op errors.Op = "wallet.validateHeaderChainDifficulties"
   832  
   833  	inMainChain, _ := w.txStore.BlockInMainChain(dbtx, &chain[0].Header.PrevBlock)
   834  	if !inMainChain {
   835  		return nil, errors.E(op, errors.Bug, "parent of chain[0] is not in main chain")
   836  	}
   837  
   838  	var parent *wire.BlockHeader
   839  
   840  	for ; idx < len(chain); idx++ {
   841  		n := chain[idx]
   842  		h := n.Header
   843  		hash := n.Hash
   844  		if parent == nil && h.Height != 0 {
   845  			if idx == 0 {
   846  				var err error
   847  				parent, err = w.txStore.GetBlockHeader(dbtx, &h.PrevBlock)
   848  				if err != nil {
   849  					return nil, err
   850  				}
   851  			} else {
   852  				parent = chain[idx-1].Header
   853  			}
   854  		}
   855  
   856  		// Validate advertised and performed work
   857  		err := w.checkDifficultyPositional(dbtx, h, parent, chain)
   858  		if err != nil {
   859  			return nil, errors.E(op, err)
   860  		}
   861  		// Check V1 Proof of Work
   862  		err = blockchain.CheckProofOfWork(hash, h.Bits, w.chainParams.PowLimit)
   863  		if err != nil {
   864  			// Check V2 Proof of Work
   865  			blake3PowHash := n.Header.PowHashV2()
   866  			err = blockchain.CheckProofOfWork(&blake3PowHash, h.Bits,
   867  				w.chainParams.PowLimit)
   868  		}
   869  		if err != nil {
   870  			return chain[idx:], errors.E(op, errors.Consensus, err)
   871  		}
   872  
   873  		// Validate ticket price
   874  		if deployments.DCP0001.Active(int32(h.Height), w.chainParams.Net) {
   875  			sdiff, err := w.nextRequiredDCP0001PoSDifficulty(dbtx, parent, chain)
   876  			if err != nil {
   877  				return nil, errors.E(op, err)
   878  			}
   879  			if dcrutil.Amount(h.SBits) != sdiff {
   880  				err := errors.Errorf("%v has invalid PoS difficulty, got %v, want %v",
   881  					hash, dcrutil.Amount(h.SBits), sdiff)
   882  				return chain[idx:], errors.E(op, errors.Consensus, err)
   883  			}
   884  		}
   885  
   886  		parent = h
   887  	}
   888  
   889  	return nil, nil
   890  }