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 }