github.com/decred/dcrd/blockchain@v1.2.1/subsidy_test.go (about)

     1  // Copyright (c) 2013-2015 The btcsuite developers
     2  // Copyright (c) 2015-2019 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 blockchain
     7  
     8  import (
     9  	"testing"
    10  
    11  	"github.com/decred/dcrd/chaincfg"
    12  )
    13  
    14  func TestBlockSubsidy(t *testing.T) {
    15  	mainnet := &chaincfg.MainNetParams
    16  	reductionInterval := mainnet.SubsidyReductionInterval
    17  	stakeValidationHeight := mainnet.StakeValidationHeight
    18  	votesPerBlock := mainnet.TicketsPerBlock
    19  
    20  	// subsidySum returns the sum of the individual subsidy types for the given
    21  	// height.  Note that this value is not exactly the same as the full subsidy
    22  	// originally used to calculate the individual proportions due to the use
    23  	// of integer math.
    24  	cache := NewSubsidyCache(0, mainnet)
    25  	subsidySum := func(height int64) int64 {
    26  		work := CalcBlockWorkSubsidy(cache, height, votesPerBlock, mainnet)
    27  		vote := CalcStakeVoteSubsidy(cache, height, mainnet) * int64(votesPerBlock)
    28  		treasury := CalcBlockTaxSubsidy(cache, height, votesPerBlock, mainnet)
    29  		return work + vote + treasury
    30  	}
    31  
    32  	// Calculate the total possible subsidy.
    33  	totalSubsidy := mainnet.BlockOneSubsidy()
    34  	for reductionNum := int64(0); ; reductionNum++ {
    35  		// The first interval contains a few special cases:
    36  		// 1) Block 0 does not produce any subsidy
    37  		// 2) Block 1 consists of a special initial coin distribution
    38  		// 3) Votes do not produce subsidy until voting begins
    39  		if reductionNum == 0 {
    40  			// Account for the block up to the point voting begins ignoring the
    41  			// first two special blocks.
    42  			subsidyCalcHeight := int64(2)
    43  			nonVotingBlocks := stakeValidationHeight - subsidyCalcHeight
    44  			totalSubsidy += subsidySum(subsidyCalcHeight) * nonVotingBlocks
    45  
    46  			// Account for the blocks remaining in the interval once voting
    47  			// begins.
    48  			subsidyCalcHeight = stakeValidationHeight
    49  			votingBlocks := reductionInterval - subsidyCalcHeight
    50  			totalSubsidy += subsidySum(subsidyCalcHeight) * votingBlocks
    51  			continue
    52  		}
    53  
    54  		// Account for the all other reduction intervals until all subsidy has
    55  		// been produced.
    56  		subsidyCalcHeight := reductionNum * reductionInterval
    57  		sum := subsidySum(subsidyCalcHeight)
    58  		if sum == 0 {
    59  			break
    60  		}
    61  		totalSubsidy += sum * reductionInterval
    62  	}
    63  
    64  	if totalSubsidy != 2099999999800912 {
    65  		t.Errorf("Bad total subsidy; want 2099999999800912, got %v", totalSubsidy)
    66  	}
    67  }
    68  
    69  func TestCachedCalcBlockSubsidy(t *testing.T) {
    70  	mainnet := &chaincfg.MainNetParams
    71  
    72  	cacheA := NewSubsidyCache(0, mainnet)
    73  	_ = cacheA.CalcBlockSubsidy(mainnet.SubsidyReductionInterval + 1)
    74  
    75  	// subsidyA is internally being calculated using the last cached subsidy.
    76  	subsidyA := cacheA.CalcBlockSubsidy((mainnet.SubsidyReductionInterval * 2) + 1)
    77  
    78  	cacheB := NewSubsidyCache(0, mainnet)
    79  
    80  	// subsidyB is internally being calculated from scratch.
    81  	subsidyB := cacheB.CalcBlockSubsidy((mainnet.SubsidyReductionInterval * 2) + 1)
    82  
    83  	if subsidyA != subsidyB {
    84  		t.Fatalf("Expected equal subsidies, got sudsidyA -> %v, "+
    85  			"subsidyB -> %v", subsidyA, subsidyB)
    86  	}
    87  }