git.gammaspectra.live/P2Pool/consensus@v0.0.0-20240403173234-a039820b20c9/monero/block/reward.go (about)

     1  package block
     2  
     3  import (
     4  	"git.gammaspectra.live/P2Pool/consensus/monero"
     5  	"lukechampine.com/uint128"
     6  	"math"
     7  )
     8  
     9  func GetBaseReward(alreadyGeneratedCounts uint64) uint64 {
    10  	result := (^alreadyGeneratedCounts) >> 19
    11  	if result < monero.TailEmissionReward {
    12  		return monero.TailEmissionReward
    13  	}
    14  	return result
    15  }
    16  
    17  func GetBlockReward(medianWeight, currentBlockWeight, alreadyGeneratedCoins uint64, version uint8) (reward uint64) {
    18  	const DIFFICULTY_TARGET_V1 = 60  // seconds - before first fork
    19  	const DIFFICULTY_TARGET_V2 = 120 // seconds
    20  	const EMISSION_SPEED_FACTOR_PER_MINUTE = 20
    21  	const FINAL_SUBSIDY_PER_MINUTE = 300000000000 // 3 * pow(10, 11)
    22  	const MONEY_SUPPLY = math.MaxUint64
    23  	const CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 = 20000  //size of block (bytes) after which reward for block calculated using block size - before first fork
    24  	const CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 = 60000  //size of block (bytes) after which reward for block calculated using block size
    25  	const CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 = 300000 //size of block (bytes) after which reward for block calculated using block size - second change, from v5
    26  
    27  	target := uint64(DIFFICULTY_TARGET_V2)
    28  	if version < 2 {
    29  		target = DIFFICULTY_TARGET_V1
    30  	}
    31  
    32  	targetMinutes := target / 60
    33  
    34  	emissionSpeedFactor := EMISSION_SPEED_FACTOR_PER_MINUTE - (targetMinutes - 1)
    35  
    36  	baseReward := (MONEY_SUPPLY - alreadyGeneratedCoins) >> emissionSpeedFactor
    37  	if baseReward < (FINAL_SUBSIDY_PER_MINUTE * targetMinutes) {
    38  		baseReward = FINAL_SUBSIDY_PER_MINUTE * targetMinutes
    39  	}
    40  
    41  	fullRewardZone := func(version uint8) uint64 {
    42  		if version < 2 {
    43  			return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1
    44  		}
    45  		if version < 5 {
    46  			return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2
    47  		}
    48  		return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5
    49  	}(version)
    50  
    51  	//make it soft
    52  	if medianWeight < fullRewardZone {
    53  		medianWeight = fullRewardZone
    54  	}
    55  
    56  	if currentBlockWeight <= medianWeight {
    57  		return baseReward
    58  	}
    59  
    60  	if currentBlockWeight > 2*medianWeight {
    61  		//Block cumulative weight is too big
    62  		return 0
    63  	}
    64  
    65  	product := uint128.From64(baseReward).Mul64(2*medianWeight - currentBlockWeight)
    66  	return product.Div64(medianWeight).Div64(medianWeight).Lo
    67  }