github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/chain/chain_diff.go (about)

     1  package chain
     2  
     3  import (
     4  	"math/big"
     5  	"github.com/piotrnar/gocoin/lib/btc"
     6  )
     7  
     8  const (
     9  	POWRetargetSpam = 14 * 24 * 60 * 60 // two weeks
    10  	TargetSpacing = 10 * 60
    11  	targetInterval = POWRetargetSpam / TargetSpacing
    12  )
    13  
    14  func (ch *Chain) GetNextWorkRequired(lst *BlockTreeNode, ts uint32) (res uint32) {
    15  	// Genesis block
    16  	if lst.Parent == nil {
    17  		return ch.Consensus.MaxPOWBits
    18  	}
    19  
    20  	if ((lst.Height+1) % targetInterval) != 0 {
    21  		// Special difficulty rule for testnet:
    22  		if ch.testnet() {
    23  			// If the new block's timestamp is more than 2* 10 minutes
    24  			// then allow mining of a min-difficulty block.
    25  			if ts > lst.Timestamp() + TargetSpacing*2 {
    26  				return ch.Consensus.MaxPOWBits
    27  			} else {
    28  				// Return the last non-special-min-difficulty-rules-block
    29  				prv := lst
    30  				for prv.Parent!=nil && (prv.Height%targetInterval)!=0 && prv.Bits()==ch.Consensus.MaxPOWBits {
    31  					prv = prv.Parent
    32  				}
    33  				return prv.Bits()
    34  			}
    35  		}
    36  		return lst.Bits()
    37  	}
    38  
    39  	prv := lst
    40  	for i:=0; i<targetInterval-1; i++ {
    41  		prv = prv.Parent
    42  	}
    43  
    44  	actualTimespan := int64(lst.Timestamp() - prv.Timestamp())
    45  
    46  	if actualTimespan < POWRetargetSpam/4 {
    47  		actualTimespan = POWRetargetSpam/4
    48  	}
    49  	if actualTimespan > POWRetargetSpam*4 {
    50  		actualTimespan = POWRetargetSpam*4
    51  	}
    52  
    53  	// Retarget
    54  	bnewbn := btc.SetCompact(lst.Bits())
    55  	bnewbn.Mul(bnewbn, big.NewInt(actualTimespan))
    56  	bnewbn.Div(bnewbn, big.NewInt(POWRetargetSpam))
    57  
    58  	if bnewbn.Cmp(ch.Consensus.MaxPOWValue) > 0 {
    59  		bnewbn = ch.Consensus.MaxPOWValue
    60  	}
    61  
    62  	res = btc.GetCompact(bnewbn)
    63  
    64  	return
    65  }
    66  
    67  // MorePOW returns true if b1 has more POW than b2.
    68  func (b1 *BlockTreeNode) MorePOW(b2 *BlockTreeNode) bool {
    69  	var b1sum, b2sum float64
    70  	for b1.Height > b2.Height {
    71  		b1sum += btc.GetDifficulty(b1.Bits())
    72  		b1 = b1.Parent
    73  	}
    74  	for b2.Height > b1.Height {
    75  		b2sum += btc.GetDifficulty(b2.Bits())
    76  		b2 = b2.Parent
    77  	}
    78  	for b1 != b2 {
    79  		b1sum += btc.GetDifficulty(b1.Bits())
    80  		b2sum += btc.GetDifficulty(b2.Bits())
    81  		b1 = b1.Parent
    82  		b2 = b2.Parent
    83  	}
    84  	return b1sum > b2sum
    85  }