mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-22 20:26:50 +00:00
Merge branch 'share-bin-activation'
This commit is contained in:
@@ -199,6 +199,11 @@ public class Block {
|
||||
|
||||
}
|
||||
|
||||
public boolean hasShareBin(AccountLevelShareBin shareBin, int blockHeight) {
|
||||
AccountLevelShareBin ourShareBin = this.getShareBin(blockHeight);
|
||||
return ourShareBin != null && shareBin.id == ourShareBin.id;
|
||||
}
|
||||
|
||||
public long distribute(long accountAmount, Map<String, Long> balanceChanges) {
|
||||
if (this.isRecipientAlsoMinter) {
|
||||
// minter & recipient the same - simpler case
|
||||
@@ -1891,12 +1896,67 @@ public class Block {
|
||||
final boolean haveFounders = !onlineFounderAccounts.isEmpty();
|
||||
|
||||
// Determine reward candidates based on account level
|
||||
List<AccountLevelShareBin> accountLevelShareBins = BlockChain.getInstance().getAccountLevelShareBins();
|
||||
for (int binIndex = 0; binIndex < accountLevelShareBins.size(); ++binIndex) {
|
||||
// Find all accounts in share bin. getShareBin() returns null for minter accounts that are also founders, so they are effectively filtered out.
|
||||
// This needs a deep copy, so the shares can be modified when tiers aren't activated yet
|
||||
List<AccountLevelShareBin> accountLevelShareBins = new ArrayList<>();
|
||||
for (AccountLevelShareBin accountLevelShareBin : BlockChain.getInstance().getAccountLevelShareBins()) {
|
||||
accountLevelShareBins.add((AccountLevelShareBin) accountLevelShareBin.clone());
|
||||
}
|
||||
|
||||
Map<Integer, List<ExpandedAccount>> accountsForShareBin = new HashMap<>();
|
||||
|
||||
// We might need to combine some share bins if they haven't reached the minimum number of minters yet
|
||||
for (int binIndex = accountLevelShareBins.size()-1; binIndex >= 0; --binIndex) {
|
||||
AccountLevelShareBin accountLevelShareBin = accountLevelShareBins.get(binIndex);
|
||||
// Object reference compare is OK as all references are read-only from blockchain config.
|
||||
List<ExpandedAccount> binnedAccounts = expandedAccounts.stream().filter(accountInfo -> accountInfo.getShareBin(this.blockData.getHeight()) == accountLevelShareBin).collect(Collectors.toList());
|
||||
|
||||
// Find all accounts in share bin. getShareBin() returns null for minter accounts that are also founders, so they are effectively filtered out.
|
||||
List<ExpandedAccount> binnedAccounts = expandedAccounts.stream().filter(accountInfo -> accountInfo.hasShareBin(accountLevelShareBin, this.blockData.getHeight())).collect(Collectors.toList());
|
||||
// Add any accounts that have been moved down from a higher tier
|
||||
List<ExpandedAccount> existingBinnedAccounts = accountsForShareBin.get(binIndex);
|
||||
if (existingBinnedAccounts != null)
|
||||
binnedAccounts.addAll(existingBinnedAccounts);
|
||||
|
||||
// Logic below may only apply to higher levels, and only for share bins with a specific range of online accounts
|
||||
if (accountLevelShareBin.levels.get(0) < BlockChain.getInstance().getShareBinActivationMinLevel() ||
|
||||
binnedAccounts.isEmpty() || binnedAccounts.size() >= BlockChain.getInstance().getMinAccountsToActivateShareBin()) {
|
||||
// Add all accounts for this share bin to the accountsForShareBin list
|
||||
accountsForShareBin.put(binIndex, binnedAccounts);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Share bin contains more than one, but less than the minimum number of minters. We treat this share bin
|
||||
// as not activated yet. In these cases, the rewards and minters are combined and paid out to the previous
|
||||
// share bin, to prevent a single or handful of accounts receiving the entire rewards for a share bin.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// - Share bin for levels 5 and 6 has 100 minters
|
||||
// - Share bin for levels 7 and 8 has 10 minters
|
||||
//
|
||||
// This is below the minimum of 30, so share bins are reconstructed as follows:
|
||||
//
|
||||
// - Share bin for levels 5 and 6 now contains 110 minters
|
||||
// - Share bin for levels 7 and 8 now contains 0 minters
|
||||
// - Share bin for levels 5 and 6 now pays out rewards for levels 5, 6, 7, and 8
|
||||
// - Share bin for levels 7 and 8 pays zero rewards
|
||||
//
|
||||
// This process is iterative, so will combine several tiers if needed.
|
||||
|
||||
// Designate this share bin as empty
|
||||
accountsForShareBin.put(binIndex, new ArrayList<>());
|
||||
|
||||
// Move the accounts originally intended for this share bin to the previous one
|
||||
accountsForShareBin.put(binIndex - 1, binnedAccounts);
|
||||
|
||||
// Move the block reward from this share bin to the previous one
|
||||
AccountLevelShareBin previousShareBin = accountLevelShareBins.get(binIndex - 1);
|
||||
previousShareBin.share += accountLevelShareBin.share;
|
||||
accountLevelShareBin.share = 0L;
|
||||
}
|
||||
|
||||
// Now loop through (potentially modified) share bins and determine the reward candidates
|
||||
for (int binIndex = 0; binIndex < accountLevelShareBins.size(); ++binIndex) {
|
||||
AccountLevelShareBin accountLevelShareBin = accountLevelShareBins.get(binIndex);
|
||||
List<ExpandedAccount> binnedAccounts = accountsForShareBin.get(binIndex);
|
||||
|
||||
// No online accounts in this bin? Skip to next one
|
||||
if (binnedAccounts.isEmpty())
|
||||
|
@@ -104,10 +104,23 @@ public class BlockChain {
|
||||
private List<RewardByHeight> rewardsByHeight;
|
||||
|
||||
/** Share of block reward/fees by account level */
|
||||
public static class AccountLevelShareBin {
|
||||
public static class AccountLevelShareBin implements Cloneable {
|
||||
public int id;
|
||||
public List<Integer> levels;
|
||||
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
||||
public long share;
|
||||
|
||||
public Object clone() {
|
||||
AccountLevelShareBin shareBinCopy = new AccountLevelShareBin();
|
||||
List<Integer> levelsCopy = new ArrayList<>();
|
||||
for (Integer level : this.levels) {
|
||||
levelsCopy.add(level);
|
||||
}
|
||||
shareBinCopy.id = this.id;
|
||||
shareBinCopy.levels = levelsCopy;
|
||||
shareBinCopy.share = this.share;
|
||||
return shareBinCopy;
|
||||
}
|
||||
}
|
||||
private List<AccountLevelShareBin> sharesByLevel;
|
||||
/** Generated lookup of share-bin by account level */
|
||||
@@ -121,6 +134,12 @@ public class BlockChain {
|
||||
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
||||
private Long qoraPerQortReward;
|
||||
|
||||
/** Minimum number of accounts before a share bin is considered activated */
|
||||
private int minAccountsToActivateShareBin;
|
||||
|
||||
/** Min level at which share bin activation takes place; lower levels allow less than minAccountsPerShareBin */
|
||||
private int shareBinActivationMinLevel;
|
||||
|
||||
/**
|
||||
* Number of minted blocks required to reach next level from previous.
|
||||
* <p>
|
||||
@@ -362,6 +381,14 @@ public class BlockChain {
|
||||
return this.qoraPerQortReward;
|
||||
}
|
||||
|
||||
public int getMinAccountsToActivateShareBin() {
|
||||
return this.minAccountsToActivateShareBin;
|
||||
}
|
||||
|
||||
public int getShareBinActivationMinLevel() {
|
||||
return this.shareBinActivationMinLevel;
|
||||
}
|
||||
|
||||
public int getMinAccountLevelToMint() {
|
||||
return this.minAccountLevelToMint;
|
||||
}
|
||||
|
@@ -39,14 +39,16 @@
|
||||
{ "height": 3110401, "reward": 2.00 }
|
||||
],
|
||||
"sharesByLevel": [
|
||||
{ "levels": [ 1, 2 ], "share": 0.05 },
|
||||
{ "levels": [ 3, 4 ], "share": 0.10 },
|
||||
{ "levels": [ 5, 6 ], "share": 0.15 },
|
||||
{ "levels": [ 7, 8 ], "share": 0.20 },
|
||||
{ "levels": [ 9, 10 ], "share": 0.25 }
|
||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||
],
|
||||
"qoraHoldersShare": 0.20,
|
||||
"qoraPerQortReward": 250,
|
||||
"minAccountsToActivateShareBin": 30,
|
||||
"shareBinActivationMinLevel": 7,
|
||||
"blocksNeededByLevel": [ 7200, 64800, 129600, 172800, 244000, 345600, 518400, 691200, 864000, 1036800 ],
|
||||
"blockTimingsByHeight": [
|
||||
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
|
||||
|
Reference in New Issue
Block a user