// CalcBlockWorkSubsidy calculates the proof of work subsidy for a block as a // proportion of the total subsidy. func CalcBlockWorkSubsidy(height int64, voters uint16, params *chaincfg.Params) int64 { subsidy := calcBlockSubsidy(height, params) proportionWork := int64(params.WorkRewardProportion) proportions := int64(params.TotalSubsidyProportions()) subsidy *= proportionWork subsidy /= proportions // Ignore the voters field of the header before we're at a point // where there are any voters. if height < params.StakeValidationHeight { return subsidy } // If there are no voters, subsidy is 0. The block will fail later anyway. if voters == 0 { return 0 } // Adjust for the number of voters. This shouldn't ever overflow if you start // with 50 * 10^8 Atoms and voters and potentialVoters are uint16. potentialVoters := params.TicketsPerBlock actual := (int64(voters) * subsidy) / int64(potentialVoters) return actual }
// CalcBlockTaxSubsidy calculates the subsidy for the organization address in the // coinbase. // // Safe for concurrent access. func CalcBlockTaxSubsidy(height int64, voters uint16, params *chaincfg.Params) int64 { if params.BlockTaxProportion == 0 { return 0 } subsidy := calcBlockSubsidy(int64(height), params) proportionTax := int64(params.BlockTaxProportion) proportions := int64(params.TotalSubsidyProportions()) subsidy *= proportionTax subsidy /= proportions // Assume all voters 'present' before stake voting is turned on. if height < params.StakeValidationHeight { voters = 5 } // If there are no voters, subsidy is 0. The block will fail later anyway. if voters == 0 && height >= params.StakeValidationHeight { return 0 } // Adjust for the number of voters. This shouldn't ever overflow if you start // with 50 * 10^8 Atoms and voters and potentialVoters are uint16. potentialVoters := params.TicketsPerBlock adjusted := (int64(voters) * subsidy) / int64(potentialVoters) return adjusted }
// CalcStakeVoteSubsidy calculates the subsidy for a stake vote based on the height // of its input SStx. // // Safe for concurrent access. func CalcStakeVoteSubsidy(height int64, params *chaincfg.Params) int64 { // Calculate the actual reward for this block, then further reduce reward // proportional to StakeRewardProportion. // Note that voters/potential voters is 1, so that vote reward is calculated // irrespective of block reward. subsidy := calcBlockSubsidy(height, params) proportionStake := int64(params.StakeRewardProportion) proportions := int64(params.TotalSubsidyProportions()) subsidy *= proportionStake subsidy /= (proportions * int64(params.TicketsPerBlock)) return subsidy }
// CalcBlockSubsidy returns the subsidy amount a block at the provided height // should have. This is mainly used for determining how much the coinbase for // newly generated blocks awards as well as validating the coinbase for blocks // has the expected value. // // Subsidy calculation for exponential reductions: // 0 for i in range (0, height / ReductionInterval): // 1 subsidy *= MulSubsidy // 2 subsidy /= DivSubsidy // // Safe for concurrent access. func calcBlockSubsidy(height int64, params *chaincfg.Params) int64 { // Block height 1 subsidy is 'special' and used to // distribute initial tokens, if any. if height == 1 { return params.BlockOneSubsidy() } iterations := height / params.ReductionInterval subsidy := params.BaseSubsidy // You could stick all these values in a LUT for faster access if you // wanted to, but this calculation is already really fast until you // get very very far into the blockchain. The other method you could // use is storing the total subsidy in a block node and do the // multiplication and division when needed when adding a block. if iterations > 0 { for i := int64(0); i < iterations; i++ { subsidy *= params.MulSubsidy subsidy /= params.DivSubsidy } } return subsidy }