mirror of
https://github.com/Qortal/qortal.git
synced 2025-02-11 17:55:50 +00:00
Admin replace founders hardfork and online validation fail-safe hardfork.
This commit is contained in:
parent
4f0aabfb36
commit
3952705edd
@ -23,6 +23,7 @@ import org.qortal.data.at.ATStateData;
|
||||
import org.qortal.data.block.BlockData;
|
||||
import org.qortal.data.block.BlockSummaryData;
|
||||
import org.qortal.data.block.BlockTransactionData;
|
||||
import org.qortal.data.group.GroupAdminData;
|
||||
import org.qortal.data.network.OnlineAccountData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.repository.*;
|
||||
@ -170,6 +171,19 @@ public class Block {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Effective Minting Level
|
||||
*
|
||||
* @return the effective minting level, if a data exception is thrown, it catches the exception and returns a zero
|
||||
*/
|
||||
public int getEffectiveMintingLevel() {
|
||||
try {
|
||||
return this.mintingAccount.getEffectiveMintingLevel();
|
||||
} catch (DataException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public Account getMintingAccount() {
|
||||
return this.mintingAccount;
|
||||
}
|
||||
@ -186,7 +200,7 @@ public class Block {
|
||||
* @return account-level share "bin" from blockchain config, or null if founder / none found
|
||||
*/
|
||||
public AccountLevelShareBin getShareBin(int blockHeight) {
|
||||
if (this.isMinterFounder)
|
||||
if (this.isMinterFounder && blockHeight < BlockChain.getInstance().getAdminsReplaceFoundersHeight())
|
||||
return null;
|
||||
|
||||
final int accountLevel = this.mintingAccountData.getLevel();
|
||||
@ -736,15 +750,7 @@ public class Block {
|
||||
List<ExpandedAccount> expandedAccounts = new ArrayList<>();
|
||||
|
||||
for (RewardShareData rewardShare : this.cachedOnlineRewardShares) {
|
||||
int groupId = BlockChain.getInstance().getMintingGroupId();
|
||||
String address = rewardShare.getMinter();
|
||||
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(groupId, address);
|
||||
|
||||
if (this.getBlockData().getHeight() < BlockChain.getInstance().getFixBatchRewardHeight())
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
||||
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getFixBatchRewardHeight() && isMinterGroupMember)
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
||||
expandedAccounts.add(new ExpandedAccount(repository, rewardShare));
|
||||
}
|
||||
|
||||
this.cachedExpandedAccounts = expandedAccounts;
|
||||
@ -1156,20 +1162,32 @@ public class Block {
|
||||
|
||||
// After feature trigger, require all online account minters to be greater than level 0
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getOnlineAccountMinterLevelValidationHeight()) {
|
||||
List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||
for (ExpandedAccount account : expandedAccounts) {
|
||||
int groupId = BlockChain.getInstance().getMintingGroupId();
|
||||
String address = account.getMintingAccount().getAddress();
|
||||
boolean isMinterGroupMember = repository.getGroupRepository().memberExists(groupId, address);
|
||||
if( this.blockData.getHeight() < BlockChain.getInstance().getOnlineValidationFailSafeHeight()) {
|
||||
List<ExpandedAccount> expandedAccounts
|
||||
= this.getExpandedAccounts().stream()
|
||||
.filter(expandedAccount -> expandedAccount.isMinterMember)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (account.getMintingAccount().getEffectiveMintingLevel() == 0)
|
||||
return ValidationResult.ONLINE_ACCOUNTS_INVALID;
|
||||
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
if (!isMinterGroupMember)
|
||||
for (ExpandedAccount account : expandedAccounts) {
|
||||
if (account.getMintingAccount().getEffectiveMintingLevel() == 0)
|
||||
return ValidationResult.ONLINE_ACCOUNTS_INVALID;
|
||||
|
||||
if (this.getBlockData().getHeight() >= BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
if (!account.isMinterMember)
|
||||
return ValidationResult.ONLINE_ACCOUNTS_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
// this.blockData.getHeight() >= BlockChain.getInstance().getOnlineValidationFailSafeHeight()
|
||||
else {
|
||||
Optional<ExpandedAccount> anyInvalidAccount
|
||||
= this.getExpandedAccounts().stream()
|
||||
.filter(
|
||||
account -> account.getEffectiveMintingLevel() == 0 ||
|
||||
!account.isMinterMember)
|
||||
.findAny();
|
||||
if( anyInvalidAccount.isPresent() ) return ValidationResult.ONLINE_ACCOUNTS_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
// If block is past a certain age then we simply assume the signatures were correct
|
||||
@ -1659,7 +1677,17 @@ public class Block {
|
||||
final List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
||||
final int maximumLevel = cumulativeBlocksByLevel.size() - 1;
|
||||
|
||||
final List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||
final List<ExpandedAccount> expandedAccounts;
|
||||
|
||||
if (this.getBlockData().getHeight() < BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
expandedAccounts = this.getExpandedAccounts().stream().collect(Collectors.toList());
|
||||
}
|
||||
else {
|
||||
expandedAccounts
|
||||
= this.getExpandedAccounts().stream()
|
||||
.filter(expandedAccount -> expandedAccount.isMinterMember)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
Set<AccountData> allUniqueExpandedAccounts = new HashSet<>();
|
||||
for (ExpandedAccount expandedAccount : expandedAccounts) {
|
||||
@ -2059,7 +2087,17 @@ public class Block {
|
||||
final List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
||||
final int maximumLevel = cumulativeBlocksByLevel.size() - 1;
|
||||
|
||||
final List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||
final List<ExpandedAccount> expandedAccounts;
|
||||
|
||||
if (this.getBlockData().getHeight() < BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
expandedAccounts = this.getExpandedAccounts().stream().collect(Collectors.toList());
|
||||
}
|
||||
else {
|
||||
expandedAccounts
|
||||
= this.getExpandedAccounts().stream()
|
||||
.filter(expandedAccount -> expandedAccount.isMinterMember)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
Set<AccountData> allUniqueExpandedAccounts = new HashSet<>();
|
||||
for (ExpandedAccount expandedAccount : expandedAccounts) {
|
||||
@ -2263,7 +2301,17 @@ public class Block {
|
||||
List<BlockRewardCandidate> rewardCandidates = new ArrayList<>();
|
||||
|
||||
// All online accounts
|
||||
final List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||
final List<ExpandedAccount> expandedAccounts;
|
||||
|
||||
if (this.getBlockData().getHeight() < BlockChain.getInstance().getFixBatchRewardHeight()) {
|
||||
expandedAccounts = this.getExpandedAccounts().stream().collect(Collectors.toList());
|
||||
}
|
||||
else {
|
||||
expandedAccounts
|
||||
= this.getExpandedAccounts().stream()
|
||||
.filter(expandedAccount -> expandedAccount.isMinterMember)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/*
|
||||
* Distribution rules:
|
||||
@ -2388,7 +2436,7 @@ public class Block {
|
||||
final long qoraHoldersShare = BlockChain.getInstance().getQoraHoldersShareAtHeight(this.blockData.getHeight());
|
||||
|
||||
// Perform account-level-based reward scaling if appropriate
|
||||
if (!haveFounders) {
|
||||
if (!haveFounders && this.blockData.getHeight() < BlockChain.getInstance().getAdminsReplaceFoundersHeight() ) {
|
||||
// Recalculate distribution ratios based on candidates
|
||||
|
||||
// Nothing shared? This shouldn't happen
|
||||
@ -2424,7 +2472,7 @@ public class Block {
|
||||
}
|
||||
|
||||
// Add founders as reward candidate if appropriate
|
||||
if (haveFounders) {
|
||||
if (haveFounders && this.blockData.getHeight() < BlockChain.getInstance().getAdminsReplaceFoundersHeight()) {
|
||||
// Yes: add to reward candidates list
|
||||
BlockRewardDistributor founderDistributor = (distributionAmount, balanceChanges) -> distributeBlockRewardShare(distributionAmount, onlineFounderAccounts, balanceChanges);
|
||||
|
||||
@ -2432,10 +2480,77 @@ public class Block {
|
||||
BlockRewardCandidate rewardCandidate = new BlockRewardCandidate("Founders", foundersShare, founderDistributor);
|
||||
rewardCandidates.add(rewardCandidate);
|
||||
}
|
||||
else if (this.blockData.getHeight() >= BlockChain.getInstance().getAdminsReplaceFoundersHeight()) {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
GroupRepository groupRepository = repository.getGroupRepository();
|
||||
|
||||
// all minter admins
|
||||
List<String> minterAdmins
|
||||
= groupRepository.getGroupAdmins(BlockChain.getInstance().getMintingGroupId()).stream()
|
||||
.map(GroupAdminData::getAdmin)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// all minter admins that are online
|
||||
List<ExpandedAccount> onlineMinterAdminAccounts
|
||||
= expandedAccounts.stream()
|
||||
.filter(expandedAccount -> minterAdmins.contains(expandedAccount.getMintingAccount().getAddress()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
BlockRewardDistributor minterAdminDistributor
|
||||
= (distributionAmount, balanceChanges)
|
||||
->
|
||||
distributeBlockRewardShare(distributionAmount, onlineMinterAdminAccounts, balanceChanges);
|
||||
|
||||
long adminShare = 1_00000000 - totalShares;
|
||||
|
||||
long minterAdminShare = adminShare / 2;
|
||||
BlockRewardCandidate minterAdminRewardCandidate
|
||||
= new BlockRewardCandidate("Minter Admins", minterAdminShare, minterAdminDistributor);
|
||||
rewardCandidates.add(minterAdminRewardCandidate);
|
||||
|
||||
totalShares -= adminShare;
|
||||
|
||||
// all dev admins
|
||||
List<String> devAdminAddresses
|
||||
= groupRepository.getGroupAdmins(1).stream()
|
||||
.map(GroupAdminData::getAdmin)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
BlockRewardDistributor devAdminDistributor
|
||||
= (distributionAmount, balanceChanges) -> distributeToAccounts(distributionAmount, devAdminAddresses, balanceChanges);
|
||||
|
||||
long devAdminShare = 1_00000000 - totalShares;
|
||||
BlockRewardCandidate devAdminRewardCandidate
|
||||
= new BlockRewardCandidate("Dev Admins", devAdminShare,devAdminDistributor);
|
||||
rewardCandidates.add(devAdminRewardCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
return rewardCandidates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Distribute To Accounts
|
||||
*
|
||||
* Merges distribute shares to a map of distribution shares.
|
||||
*
|
||||
* @param distributionAmount the amount to distribute
|
||||
* @param accountAddressess the addresses to distribute to
|
||||
* @param balanceChanges the map of distribution shares, this gets appended to
|
||||
*
|
||||
* @return the total amount mapped to addresses for distribution
|
||||
*/
|
||||
public static long distributeToAccounts(long distributionAmount, List<String> accountAddressess, Map<String, Long> balanceChanges) {
|
||||
|
||||
long distibutionShare = distributionAmount / accountAddressess.size();
|
||||
|
||||
for(String accountAddress : accountAddressess ) {
|
||||
balanceChanges.merge(accountAddress, distibutionShare, Long::sum);
|
||||
}
|
||||
|
||||
return distibutionShare * accountAddressess.size();
|
||||
}
|
||||
|
||||
private static long distributeBlockRewardShare(long distributionAmount, List<ExpandedAccount> accounts, Map<String, Long> balanceChanges) {
|
||||
// Collate all expanded accounts by minting account
|
||||
Map<String, List<ExpandedAccount>> accountsByMinter = new HashMap<>();
|
||||
|
@ -88,7 +88,9 @@ public class BlockChain {
|
||||
onlyMintWithNameHeight,
|
||||
removeOnlyMintWithNameHeight,
|
||||
groupMemberCheckHeight,
|
||||
fixBatchRewardHeight
|
||||
fixBatchRewardHeight,
|
||||
adminsReplaceFoundersHeight,
|
||||
onlineValidationFailSafeHeight
|
||||
}
|
||||
|
||||
// Custom transaction fees
|
||||
@ -662,6 +664,14 @@ public class BlockChain {
|
||||
return this.featureTriggers.get(FeatureTrigger.fixBatchRewardHeight.name()).intValue();
|
||||
}
|
||||
|
||||
public int getAdminsReplaceFoundersHeight() {
|
||||
return this.featureTriggers.get(FeatureTrigger.adminsReplaceFoundersHeight.name()).intValue();
|
||||
}
|
||||
|
||||
public int getOnlineValidationFailSafeHeight() {
|
||||
return this.featureTriggers.get(FeatureTrigger.onlineValidationFailSafeHeight.name()).intValue();
|
||||
}
|
||||
|
||||
// More complex getters for aspects that change by height or timestamp
|
||||
|
||||
public long getRewardAtHeight(int ourHeight) {
|
||||
|
@ -113,7 +113,9 @@
|
||||
"onlyMintWithNameHeight": 1900300,
|
||||
"removeOnlyMintWithNameHeight": 1935500,
|
||||
"groupMemberCheckHeight": 1902700,
|
||||
"fixBatchRewardHeight": 1945900
|
||||
"fixBatchRewardHeight": 1945900,
|
||||
"adminsReplaceFoundersHeight": 9999999,
|
||||
"onlineValidationFailSafeHeight": 9999999
|
||||
},
|
||||
"checkpoints": [
|
||||
{ "height": 1136300, "signature": "3BbwawEF2uN8Ni5ofpJXkukoU8ctAPxYoFB7whq9pKfBnjfZcpfEJT4R95NvBDoTP8WDyWvsUvbfHbcr9qSZuYpSKZjUQTvdFf6eqznHGEwhZApWfvXu6zjGCxYCp65F4jsVYYJjkzbjmkCg5WAwN5voudngA23kMK6PpTNygapCzXt" }
|
||||
|
Loading…
x
Reference in New Issue
Block a user