Skip to content

Commit

Permalink
prototyping
Browse files Browse the repository at this point in the history
  • Loading branch information
notJoon committed Jan 15, 2025
1 parent b1ce569 commit 9112f66
Showing 1 changed file with 87 additions and 0 deletions.
87 changes: 87 additions & 0 deletions staker/reward_calculation_pool_tier.gno
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ func (self *TierRatio) Get(tier uint64) uint64 {
}
}

type HalvingInfo interface {
// Return a list of halving blocks within the interval (start, end) in ascending order
GetHalvingBlocksInRange(start, end uint64) []uint64

// Returns the emission value at that block (after half-life), etc.
GetEmissionAfterHalving(currentEmission uint64) uint64
}

// PoolTier manages pool counts, ratios, and rewards for different tiers.
//
// Fields:
Expand All @@ -133,6 +141,11 @@ type PoolTier struct {
// rewardCache [4]*RewardCacheTree // blockNumber -> uint64
lastRewardCacheHeight *uint64

currentEmission uint64

// Field for queries to get a list of halving blocks, halving intervals, etc.
halvingInfo HalvingInfo

emissionUpdate func(uint64, uint64) en.EmissionUpdate
}

Expand Down Expand Up @@ -204,6 +217,7 @@ func (self *PoolTier) changeTier(currentHeight uint64, pools *Pools, poolPath st
println("[", currentHeight, "] changeTier Start -> poolPath : ", poolPath, ", nextTier : ", nextTier)
self.cacheReward(currentHeight, pools)

// same as prev. no need to update
currentTier := self.CurrentTier(poolPath)
if currentTier == nextTier {
return
Expand Down Expand Up @@ -245,6 +259,52 @@ func CalculateTierReward(currentEmission uint64, tierRatio *TierRatio, tier uint
// cacheReward MUST be called before calculating any position reward
// There MUST be no ratio/count/tier change during the emissionUpdates
// (due to calling cacheReward() at the start of changeTier(), this holds true).
func (self *PoolTier) cacheReward(currentHeight uint64, pools *Pools) {
lastHeight := *self.lastRewardCacheHeight
if currentHeight <= lastHeight {
// no need to check
return
}

// find halving blocks in range
halvingBlocks := self.halvingInfo.GetHalvingBlocksInRange(lastHeight+1, currentHeight)

cursor := lastHeight
currentEmission := self.currentEmission

for _, hvBlock := range halvingBlocks {
if hvBlock <= cursor {
continue
}

if hvBlock > currentHeight {
break
}

// caching: (cursor+1 ~ hvBlock)
startBlock := cursor
endBlock := hvBlock
if endBlock > startBlock {
self.applyCacheToAllPools(pools, startBlock, endBlock, currentEmission)
cursor = endBlock - 1
}

// halve emissions when halvingBlock is reached
currentEmission = self.halvingInfo.GetEmissionAfterHalving(currentEmission)
}

// remaining range (cursor+1 ~ currentHeight)
if cursor < currentHeight {
self.applyCacheToAllPools(pools, cursor, currentHeight, currentEmission)
cursor = currentHeight
}

// update lastRewardCacheHeight and currentEmission
*self.lastRewardCacheHeight = currentHeight
self.currentEmission = currentEmission
}

/*
func (self *PoolTier) cacheReward(currentHeight uint64, pools *Pools) {
// PoolTier.cacheReward is executed only when emissionUpdate is not empty, which means:
// - there is a new halving event
Expand Down Expand Up @@ -282,6 +342,33 @@ func (self *PoolTier) cacheReward(currentHeight uint64, pools *Pools) {
*self.lastRewardCacheHeight = currentHeight
println("[", currentHeight, "] cacheReward End : lastRewardCacheHeight ", *self.lastRewardCacheHeight)
}
*/

func (self *PoolTier) applyCacheToAllPools(pools *Pools, startBlock, endBlock, emissionInThisInterval uint64) {
if startBlock >= endBlock {
return
}

// calculate denominator and number of pools in each tier
counts := self.CurrentAllTierCounts()
denominators := self.tierRatio.IntoRewardDenominators(counts)

// apply cache to all pools
self.membership.Iterate("", "", func(key string, value interface{}) bool {
tierNum := value.(uint64)
pool, ok := pools.Get(key)
if !ok {
return false
}

// real reward
partialReward := ApplyDenominator(emissionInThisInterval, denominators[tierNum])

// accumulate the reward for the interval (startBlock to endBlock) in the Pool
pool.cacheInternalReward(startBlock, endBlock, partialReward)
return false
})
}

func (self *PoolTier) IsInternallyIncentivizedPool(currentHeight uint64, poolPath string) bool {
return self.CurrentTier(poolPath) > 0
Expand Down

0 comments on commit 9112f66

Please sign in to comment.