Skip to content

Commit 1e6b38e

Browse files
committed
fix: ajust plot and report feature according to the latest changes
1 parent 60ea7d2 commit 1e6b38e

21 files changed

+295
-76
lines changed

report/treasury_calculation_result.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/org/cardanofoundation/rewards/calculation/EpochCalculation.java

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,21 @@ public static EpochCalculationResult calculateEpochRewardPots(final int epoch, f
2727
final List<String> poolsThatProducedBlocksInEpoch,
2828
final List<PoolHistory> poolHistories,
2929
final HashSet<String> lateDeregisteredAccounts,
30-
final HashSet<String> accountsRegisteredInThePast,
30+
final HashSet<String> registeredAccountsSinceLastEpoch,
31+
final HashSet<String> registeredAccountsUntilNow,
3132
final HashSet<String> sharedPoolRewardAddressesWithoutReward) {
3233
final EpochCalculationResult epochCalculationResult = EpochCalculationResult.builder().epoch(epoch).build();
3334

35+
if (epoch < 209) {
36+
epochCalculationResult.setReserves(MAINNET_SHELLEY_INITIAL_RESERVES);
37+
epochCalculationResult.setTreasury(MAINNET_SHELLEY_INITIAL_TREASURY);
38+
epochCalculationResult.setTotalDistributedRewards(BigInteger.ZERO);
39+
epochCalculationResult.setTotalRewardsPot(BigInteger.ZERO);
40+
epochCalculationResult.setTotalPoolRewardsPot(BigInteger.ZERO);
41+
epochCalculationResult.setTotalAdaInCirculation(MAINNET_SHELLEY_INITIAL_UTXO);
42+
return epochCalculationResult;
43+
}
44+
3445
double treasuryGrowthRate = 0.2;
3546
double monetaryExpandRate = 0.003;
3647
double decentralizationParameter = 1;
@@ -67,25 +78,41 @@ public static EpochCalculationResult calculateEpochRewardPots(final int epoch, f
6778
final BigInteger stakePoolRewardsPot = rewardPot.subtract(treasuryCut);
6879

6980
// The sum of all the refunds attached to unregistered reward accounts are added to the
70-
// treasury (see: Pool Reap Transition, p.53, figure 40, shely-ledger.pdf)
81+
// treasury (see: Pool Reap Transition, p.53, figure 40, shelley-ledger.pdf)
7182
if (retiredPools.size() > 0) {
7283
List<String> rewardAddressesOfRetiredPools = retiredPools.stream().map(PoolDeregistration::getRewardAddress).toList();
7384
List<String> deregisteredOwnerAccounts = deregisteredAccounts.stream()
7485
.filter(rewardAddressesOfRetiredPools::contains).toList();
7586
List<String> lateDeregisteredOwnerAccounts = lateDeregisteredAccounts.stream()
7687
.filter(rewardAddressesOfRetiredPools::contains).toList();
88+
List<String> ownerAccountsRegisteredInThePast = registeredAccountsUntilNow.stream()
89+
.filter(rewardAddressesOfRetiredPools::contains).toList();
7790

78-
if (deregisteredOwnerAccounts.size() > 0 || lateDeregisteredOwnerAccounts.size() > 0) {
79-
treasuryForCurrentEpoch = treasuryForCurrentEpoch.add(POOL_DEPOSIT_IN_LOVELACE);
91+
/* Check if the reward address of the retired pool has been unregistered before
92+
or if the reward address has been unregistered after the randomness stabilization window
93+
or if the reward address has not been registered at all */
94+
for (PoolDeregistration retiredPool : retiredPools) {
95+
String rewardAddress = retiredPool.getRewardAddress();
96+
if (deregisteredOwnerAccounts.contains(rewardAddress) ||
97+
lateDeregisteredOwnerAccounts.contains(rewardAddress) ||
98+
!ownerAccountsRegisteredInThePast.contains(rewardAddress)) {
99+
// If the reward address has been unregistered, the deposit is added to the treasury
100+
treasuryForCurrentEpoch = treasuryForCurrentEpoch.add(POOL_DEPOSIT_IN_LOVELACE);
101+
}
80102
}
81103
}
82104
// Check if there was a MIR Certificate in the previous epoch
83105
BigInteger treasuryWithdrawals = BigInteger.ZERO;
106+
BigInteger calculatedReserve = subtract(reserveInPreviousEpoch, subtract(rewardPot, totalFeesForCurrentEpoch));
107+
84108
for (MirCertificate mirCertificate : mirCertificates) {
85109
if (mirCertificate.getPot() == MirPot.TREASURY) {
86110
treasuryWithdrawals = treasuryWithdrawals.add(mirCertificate.getTotalRewards());
111+
} else if (mirCertificate.getPot() == MirPot.RESERVES) {
112+
calculatedReserve = calculatedReserve.subtract(mirCertificate.getTotalRewards());
87113
}
88114
}
115+
89116
treasuryForCurrentEpoch = treasuryForCurrentEpoch.subtract(treasuryWithdrawals);
90117

91118
BigInteger totalDistributedRewards = BigInteger.ZERO;
@@ -95,7 +122,7 @@ public static EpochCalculationResult calculateEpochRewardPots(final int epoch, f
95122

96123
int i = 1;
97124
for (String poolId : poolsThatProducedBlocksInEpoch) {
98-
log.info("[" + i + " / " + poolsThatProducedBlocksInEpoch.size() + "] Processing pool: " + poolId);
125+
log.debug("[" + i + " / " + poolsThatProducedBlocksInEpoch.size() + "] Processing pool: " + poolId);
99126
PoolHistory poolHistory = poolHistories.stream().filter(history -> history.getPoolId().equals(poolId)).findFirst().orElse(null);
100127

101128
PoolRewardCalculationResult poolRewardCalculationResult = PoolRewardCalculationResult
@@ -132,7 +159,7 @@ public static EpochCalculationResult calculateEpochRewardPots(final int epoch, f
132159
blocksInEpoch, protocolParameters,
133160
adaInCirculation, activeStakeInEpoch, stakePoolRewardsPot,
134161
poolHistory.getOwnerActiveStake(), poolHistory.getOwners(),
135-
delegatorAccountDeregistrations, ignoreLeaderReward, lateDeregisteredDelegators, accountsRegisteredInThePast);
162+
delegatorAccountDeregistrations, ignoreLeaderReward, lateDeregisteredDelegators, registeredAccountsSinceLastEpoch);
136163
}
137164

138165
totalDistributedRewards = add(totalDistributedRewards, poolRewardCalculationResult.getDistributedPoolReward());
@@ -141,7 +168,6 @@ public static EpochCalculationResult calculateEpochRewardPots(final int epoch, f
141168
i++;
142169
}
143170

144-
BigInteger calculatedReserve = subtract(reserveInPreviousEpoch, subtract(rewardPot, totalFeesForCurrentEpoch));
145171
BigInteger undistributedRewards = subtract(stakePoolRewardsPot, totalDistributedRewards);
146172
calculatedReserve = add(calculatedReserve, undistributedRewards);
147173
calculatedReserve = subtract(calculatedReserve, unspendableEarnedRewards);
@@ -157,9 +183,17 @@ public static EpochCalculationResult calculateEpochRewardPots(final int epoch, f
157183
calculatedReserve = calculatedReserve.add(MAINNET_BOOTSTRAP_ADDRESS_AMOUNT);
158184
}
159185

160-
log.info("Unspendable earned rewards: " + lovelaceToAda(unspendableEarnedRewards.intValue()) + " ADA");
186+
log.debug("Unspendable earned rewards: " + lovelaceToAda(unspendableEarnedRewards.intValue()) + " ADA");
161187
treasuryForCurrentEpoch = add(treasuryForCurrentEpoch, unspendableEarnedRewards);
162188

189+
TreasuryCalculationResult treasuryCalculationResult = TreasuryCalculationResult.builder()
190+
.epoch(epoch)
191+
.treasury(treasuryForCurrentEpoch)
192+
.totalRewardPot(rewardPot)
193+
.treasuryWithdrawals(treasuryWithdrawals)
194+
.unspendableEarnedRewards(unspendableEarnedRewards)
195+
.build();
196+
163197
epochCalculationResult.setTotalDistributedRewards(totalDistributedRewards);
164198
epochCalculationResult.setTotalRewardsPot(rewardPot);
165199
epochCalculationResult.setReserves(calculatedReserve);
@@ -168,6 +202,7 @@ public static EpochCalculationResult calculateEpochRewardPots(final int epoch, f
168202
epochCalculationResult.setTotalPoolRewardsPot(stakePoolRewardsPot);
169203
epochCalculationResult.setTotalAdaInCirculation(adaInCirculation);
170204
epochCalculationResult.setTotalUndistributedRewards(undistributedRewards);
205+
epochCalculationResult.setTreasuryCalculationResult(treasuryCalculationResult);
171206

172207
return epochCalculationResult;
173208
}

src/main/java/org/cardanofoundation/rewards/calculation/PoolRewardsCalculation.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.math.BigInteger;
77
import java.util.*;
88

9+
import static org.cardanofoundation.rewards.calculation.constants.RewardConstants.MAINNET_VASIL_HARDFORK_EPOCH;
910
import static org.cardanofoundation.rewards.calculation.util.BigNumberUtils.*;
1011
import static org.cardanofoundation.rewards.calculation.util.BigNumberUtils.divide;
1112

@@ -131,14 +132,28 @@ public static PoolRewardCalculationResult calculatePoolRewardInEpoch(final Strin
131132
final HashSet<String> deregisteredAccounts, final boolean ignoreLeaderReward,
132133
final HashSet<String> lateDeregisteredAccounts,
133134
final HashSet<String> accountsRegisteredInThePast) {
135+
final int earnedEpoch = poolHistoryCurrentEpoch.getEpoch();
134136
final PoolRewardCalculationResult poolRewardCalculationResult = PoolRewardCalculationResult.builder()
135-
.epoch(poolHistoryCurrentEpoch.getEpoch())
137+
.epoch(earnedEpoch)
136138
.poolId(poolId)
137139
.poolReward(BigInteger.ZERO)
138140
.distributedPoolReward(BigInteger.ZERO)
139141
.unspendableEarnedRewards(BigInteger.ZERO)
140142
.build();
141143

144+
/*
145+
babbage-ledger.pdf | 6 Forgo Reward Calculation Prefilter | p. 14
146+
147+
The reward calculation no longer filters out the unregistered stake credentials when creating
148+
a reward update. As in the Shelley era, though, they are still filtered on the epoch boundary
149+
when the reward update is applied
150+
151+
if (spendableEpoch >= MAINNET_VASIL_HARDFORK_EPOCH) {
152+
lateDeregisteredAccounts.addAll(deregisteredAccounts);
153+
deregisteredAccounts.clear();
154+
}
155+
*/
156+
142157
final BigInteger poolStake = poolHistoryCurrentEpoch.getActiveStake();
143158
final BigInteger poolPledge = poolHistoryCurrentEpoch.getPledge();
144159
final double poolMargin = poolHistoryCurrentEpoch.getMargin();
@@ -196,20 +211,20 @@ public static PoolRewardCalculationResult calculatePoolRewardInEpoch(final Strin
196211
String rewardAddress = poolRewardCalculationResult.getRewardAddress();
197212

198213
if (!accountsRegisteredInThePast.contains(rewardAddress)) {
199-
log.info(poolRewardCalculationResult.getRewardAddress() + " has never been registered. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
214+
log.debug(poolRewardCalculationResult.getRewardAddress() + " has never been registered. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
200215
poolOperatorReward = BigInteger.ZERO;
201216
} else if (deregisteredAccounts.contains(rewardAddress)) {
202-
log.info(poolRewardCalculationResult.getRewardAddress() + " has been deregistered. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
217+
log.debug(poolRewardCalculationResult.getRewardAddress() + " has been deregistered. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
203218
poolOperatorReward = BigInteger.ZERO;
204219
} else if (lateDeregisteredAccounts.contains(rewardAddress)) {
205-
log.info("[unregRU]: " + poolRewardCalculationResult.getRewardAddress() + " has been deregistered lately. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
220+
log.debug("[unregRU]: " + poolRewardCalculationResult.getRewardAddress() + " has been deregistered lately. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
206221
unspendableEarnedRewards = poolOperatorReward;
207222
poolOperatorReward = BigInteger.ZERO;
208223
}
209224

210225
if (ignoreLeaderReward) {
211226
poolOperatorReward = BigInteger.ZERO;
212-
log.info("[reward address of multiple pools] Pool " + poolId + " has been ignored. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
227+
log.debug("[reward address of multiple pools] Pool " + poolId + " has been ignored. Operator would have received " + poolOperatorReward + " but will not receive any rewards.");
213228
}
214229

215230
// Step 11: Calculate pool member reward
@@ -226,10 +241,10 @@ public static PoolRewardCalculationResult calculatePoolRewardInEpoch(final Strin
226241
poolFixedCost, divide(delegator.getActiveStake(), adaInCirculation), relativePoolStake);
227242

228243
if (deregisteredAccounts.contains(stakeAddress)) {
229-
log.info("Delegator " + stakeAddress + " has been deregistered. Delegator would have received " + memberReward + " but will not receive any rewards.");
244+
log.debug("Delegator " + stakeAddress + " has been deregistered. Delegator would have received " + memberReward + " but will not receive any rewards.");
230245
memberReward = BigInteger.ZERO;
231246
} else if (lateDeregisteredAccounts.contains(stakeAddress)) {
232-
log.info("[unregRU]: " + stakeAddress + " has been deregistered lately. Delegator would have received " + memberReward + " but will not receive any rewards.");
247+
log.debug("[unregRU]: " + stakeAddress + " has been deregistered lately. Delegator would have received " + memberReward + " but will not receive any rewards.");
233248
unspendableEarnedRewards = unspendableEarnedRewards.add(memberReward);
234249
memberReward = BigInteger.ZERO;
235250
}

src/main/java/org/cardanofoundation/rewards/calculation/TreasuryCalculation.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import org.cardanofoundation.rewards.calculation.domain.*;
44
import org.cardanofoundation.rewards.calculation.enums.AccountUpdateAction;
55

6+
import java.math.BigDecimal;
67
import java.math.BigInteger;
8+
import java.math.MathContext;
79
import java.util.List;
810

911
import static org.cardanofoundation.rewards.calculation.constants.RewardConstants.EXPECTED_SLOT_PER_EPOCH;
@@ -20,7 +22,7 @@ public class TreasuryCalculation {
2022
*/
2123
public static BigInteger calculateTotalRewardPotWithEta(double monetaryExpandRate, int totalBlocksInEpochByPools,
2224
double decentralizationParameter, BigInteger reserve, BigInteger fee) {
23-
double eta = calculateEta(totalBlocksInEpochByPools, decentralizationParameter);
25+
BigDecimal eta = calculateEta(totalBlocksInEpochByPools, decentralizationParameter);
2426
return multiplyAndFloor(reserve, monetaryExpandRate, eta).add(fee);
2527
}
2628

@@ -33,25 +35,27 @@ public static BigInteger calculateTotalRewardPotWithEta(double monetaryExpandRat
3335
*
3436
* See: https://github.com/input-output-hk/cardano-ledger/commit/c4f10d286faadcec9e4437411bce9c6c3b6e51c2
3537
*/
36-
private static double calculateEta(int totalBlocksInEpochByPools, double decentralizationParameter) {
38+
private static BigDecimal calculateEta(int totalBlocksInEpochByPools, double decentralizationParameter) {
3739
// shelley-delegation.pdf 5.4.3
3840

3941
if (decentralizationParameter >= 0.8) {
40-
return 1.0;
42+
return BigDecimal.ONE;
4143
}
4244

4345
// The number of expected blocks will be the number of slots per epoch times the active slots coefficient
44-
double activeSlotsCoeff = 0.05; // See: Non-Updatable Parameters: https://cips.cardano.org/cips/cip9/
46+
BigDecimal activeSlotsCoeff = new BigDecimal("0.05"); // See: Non-Updatable Parameters: https://cips.cardano.org/cips/cip9/
4547

4648
// decentralizationParameter is the proportion of blocks that are expected to be produced by stake pools
4749
// instead of the OBFT (Ouroboros Byzantine Fault Tolerance) nodes. It was introduced close before the Shelley era:
4850
// https://github.com/input-output-hk/cardano-ledger/commit/c4f10d286faadcec9e4437411bce9c6c3b6e51c2
49-
double expectedBlocksInNonOBFTSlots = EXPECTED_SLOT_PER_EPOCH * activeSlotsCoeff * (1 - decentralizationParameter);
51+
BigDecimal expectedBlocksInNonOBFTSlots = new BigDecimal(EXPECTED_SLOT_PER_EPOCH )
52+
.multiply(activeSlotsCoeff).multiply (new BigDecimal(1 - decentralizationParameter));
5053

5154
// eta is the ratio between the number of blocks that have been produced during the epoch, and
5255
// the expectation value of blocks that should have been produced during the epoch under
5356
// ideal conditions.
54-
return Math.min(1, totalBlocksInEpochByPools / expectedBlocksInNonOBFTSlots);
57+
MathContext mathContext = new MathContext(32);
58+
return new BigDecimal(totalBlocksInEpochByPools).divide(expectedBlocksInNonOBFTSlots, mathContext).min(BigDecimal.ONE);
5559
}
5660

5761
/*

src/main/java/org/cardanofoundation/rewards/calculation/constants/RewardConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ public class RewardConstants {
77
public static final BigInteger POOL_DEPOSIT_IN_LOVELACE = BigInteger.valueOf(500000000);
88
// https://developers.cardano.org/docs/operate-a-stake-pool/introduction-to-cardano/#slots-and-epochs
99
public static final int EXPECTED_SLOT_PER_EPOCH = 432000;
10+
public static final BigInteger MAINNET_SHELLEY_INITIAL_RESERVES = new BigInteger("13888022852926644");
11+
public static final BigInteger MAINNET_SHELLEY_INITIAL_TREASURY = new BigInteger("0");
12+
public static final BigInteger MAINNET_SHELLEY_INITIAL_UTXO = TOTAL_LOVELACE.subtract(MAINNET_SHELLEY_INITIAL_RESERVES);
1013
public static final int GENESIS_CONFIG_SECURITY_PARAMETER = 2160;
14+
public static final int MAINNET_SHELLEY_START_EPOCH = 208;
1115
public static final int MAINNET_ALLEGRA_HARDFORK_EPOCH = 236;
16+
public static final int MAINNET_VASIL_HARDFORK_EPOCH = 350;
1217
public static final BigInteger MAINNET_BOOTSTRAP_ADDRESS_AMOUNT = new BigInteger("318200635000000");
1318
public static final double ACTIVE_SLOT_COEFFICIENT = 0.05;
1419
public static final long RANDOMNESS_STABILISATION_WINDOW = Math.round(

src/main/java/org/cardanofoundation/rewards/calculation/domain/TreasuryCalculationResult.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ public class TreasuryCalculationResult {
1414
BigInteger treasury;
1515
BigInteger totalRewardPot;
1616
BigInteger treasuryWithdrawals;
17+
BigInteger unspendableEarnedRewards;
1718
}

src/main/java/org/cardanofoundation/rewards/calculation/util/BigNumberUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ public static BigInteger add(BigInteger a, BigInteger b) {
1111
return a.add(b);
1212
}
1313

14+
public static BigInteger multiplyAndFloor(BigInteger a, double b, BigDecimal c) {
15+
return new BigDecimal(a).multiply(BigDecimal.valueOf(b).multiply(c))
16+
.round(new MathContext(0, RoundingMode.FLOOR)).toBigInteger();
17+
}
18+
1419
public static BigInteger multiplyAndFloor(BigInteger a, double b, double c) {
1520
return new BigDecimal(a).multiply(BigDecimal.valueOf(b).multiply(BigDecimal.valueOf(c)))
1621
.round(new MathContext(0, RoundingMode.FLOOR)).toBigInteger();

0 commit comments

Comments
 (0)