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 }