Rewards
Miner, sharders and their delegates receive rewards each round. There is a lottery every round where a subset of the miners, sharders and their delegates are chosen to receive the rewards.
There are two types of rewards paid to miners and sharders.
- Block rewards. This is a fixed amount paid out every round. The amount is found in the smart-contract config
minersc.block_reward
field. - Income. This is a fees paid for transactions run this round.
The rewards are totalled and split between miners and sharders in the ratio minersc.share_ratio:1-minersc.share_ratio
. Usually, we want to choose share_ratio
so the payments to miners equal the payments to sharders.
total reward = block_reward + total fee payments
Every round, one of the active miners is chosen to receive all the miner rewards for that round. The miner receives a fraction equal to the chosen miner's service charge. The remaining reward is split up between the miner's delegates.
miner service charge = total_reward * share_ratio * miner's_service_charge
When paying rewards to delegates, we pay only a subset of the delegates. For miners, the number of delegates we reward is given by the setting minersc.num_miner_delegates_rewarded
. We choose at ransom minersc.num_miner_delegates_rewarded
delegates to receive rewards or all delegates if the number is less than minersc.num_miner_delegates_rewarded
. We then split the reward up between the selected delegates in ratio to their balance.
paid to a miner's delegate pools = total_reward * share_ratio * (1-miner's_service_charge)
individual delegate reward = paid to delegate pools * delegate's balance / total balances of selected delegates
Every round the 0chain selects minersc.num_sharders_rewarded
active sharders at random to receive that round's reward. The sharder share of the reward is split evenly amongst the selected sharders.
Each sharder gets a fraction of that sharder's reward, determined by the shader's service charge.
sharder service charge = total_reward * (1-share_ratio) * sharder's_service_charge / num_sharder_delegates_rewarded
Sharder delegates are rewarded similarly to miners. For each sharder, we select minersc.num_sharder_delegates_rewarded
delegates to receive a reward, or all delegates if less.
paid to a sharder's delegates = total_reward * (1-share_ratio) * (1-miner's_service_charge) / num_sharder_delegates_rewarded
individual delegate reward = paid to delegate pools * delegate's balance / total balances of selected delegates
All these values are initially set from sc.yaml
, the smart_contracts.minersc key
block_reward:
share_ratio: 0.5
num_miner_delegates_rewarded: 10
num_sharders_rewarded: 1
num_sharder_delegates_rewarded: 5
We also use the miner and sharder service charge in the calculations. A typical value for this would be 0.1
.
Every round generator adds blobber_block_rewards
transaction to the block, the only input parameter is a round for what calculation is triggered ?can we take round from the block itself?.
Amount to be rewarded is calculated by formula:
changeBalance := 1 - conf.block_reward_change_ratio
changePeriods := currentRound / conf.block_reward_change_ratio
factor := math.Pow(changeBalance, float64(changePeriods)) * conf.blobber_weight
return currency.MultFloat64(br, factor)
current config values
block_reward:
block_reward: 1
block_reward_change_period: 10000
block_reward_change_ratio: 0.1
Active blobbers are chosen from partitions we created earlier. BlobberRewardNode is added to partition every time challenge is passed.For every trigger_period: 30
new partition is created. ?how do we ensure that blobber is unique?
type BlobberRewardNode struct {
ID string `json:"id"` //blobberID
SuccessChallenges int `json:"success_challenges"`
WritePrice currency.Coin `json:"write_price"`
ReadPrice currency.Coin `json:"read_price"`
TotalData float64 `json:"total_data"`
DataRead float64 `json:"data_read"`
}
Random seed is calculated using formula
hashString := encryption.Hash(balances.GetTransaction().Hash + balances.GetBlock().PrevHash)
var randomSeed int64
randomSeed, err = strconv.ParseInt(hashString[0:15], 16, 64)
if err != nil {
return common.NewError("blobber_block_rewards_failed",
"error in creating seed"+err.Error())
}
r := rand.New(rand.NewSource(randomSeed))
For every blobber in partition there weights are calculated using formula from white paper (Alfa, Gamma, Zetta). Reward amount is distributed then among all the blobbers in the partition according to weights calculated before. Every blobber distributes its fraction of rewards according to standard algorithm among all the delegates ?provide link to algo?
Every time challenge is passed blobber and validator are rewarded.
Challenge pool stores token received from clients for it's writes and keeps them until allocation challenge is completed, tokens can be moved to the blobber in case of success, to the validator as a reward or in case of slashing, and to the client in case of failed challenge (slashing) or in case of data delete.
Every time write marker is committed a portion of tokens from allocation write pool is transferred to the challenge pool. The size written to allocation is rounded to the chunk size first (64kB as for now). Then rest duration in time units is calculated as an amount of timeunits to the allocation expiry.
rdtu = (allocation.Expiration - WriteMarker.Timestamp) / timeunit
Then the amount of tokens to be transferred to the pool is computed as
amount = size * Terms.WritePrice * rdtu
This amount is transferred to the challenge pool, also this amount is added to ChallengePoolIntegralValue
To keep track of challenge pool fraction related to a particular blobber-allocation pair integral value was introduce. It behaves exactly the same way and should be always in sync with corresponding challenge pool. It means, that the summary of integral values for every blobber for a current allocation is exactly the challenge pool balance for any moment in time.
Blobber is added to the partition for block rewards calculation on every first challenge passed this rewards period. All the fields in BlobberRewardNode except ChallengesPassed are fixed for that moment, only ChallengesPassed will be updated next time challenge is passed.
Reward is calculated based on time unit values. All the available for reward values are stored in blobber allocation itself in ChallengePoolIntegralValue
field. It is reduced every time reward is calculated
rdtu = (allocation.Expiration - PreviousCompletedChallenge.Created) / timeunit
dtu = (CurrentCompletedChallenge.Created - PreviousCompletedChallenge.Created) / timeunit
reward = (dtu / rdtu) * float64(d.ChallengePoolIntegralValue)
d.ChallengePoolIntegralValue -= reward
If intervals dtu
are even, then rewards will be split evenly between the intervals for constant ChallengePoolIntegralValue (it will be spent evenly in the intervals).
Reward then is split in two part, blobberReward and validatorReward using provided in config ratio.
validatorsReward = reward * config.validator_reward
blobberReward = reward * (1 - config.validator_reward)
Reward value is also adjusted to the success rate of a blobber. If rewards are adjusted, difference is taken from challenge pool and burnt.
partial = float64(challenge.SuccessfulTickets) / float64(challenge.TotalValidators / 2)
blobberReward = blobberReward * partial
Reward amount is distributed among all the blobbers evenly. Every blobber distributes its fraction of rewards according to standard algorithm among all the delegates.
- If provider doesn't have any delegates, then all the rewards go to provider's stake pool
- If service charge is set, then provider will be guaranteed to receive service charge
- Then value left is split among all the delegates of a provider proportionally with their weight
stakePool.Reward = stakePool.Reward + value
sp.Reward = stakePool.Reward + serviceCharge
valueLeft = value - serviceCharge
for id, pool := range sp.Pools {
ratio := pool.Balance / totalStake
reward := valueLeft * ratio
delegate.Reward = delegate.Reward, reward
valueLeft = valueLeft - reward
}
Reward amount is distributed among all the validators evenly. Every validator distributes its fraction of rewards according to standard algorithm among all the delegates ?provide link to algo?
- Home
- Introduction
- Architecture
- 0Chain Smart Contracts
- Help