forked from Qortal/qortal
Fix for incorrect blocksMinted count. Added test to cover
This commit is contained in:
parent
6d8f41ab05
commit
3fa7da5115
@ -9,9 +9,10 @@ import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -1267,42 +1268,31 @@ public class Block {
|
||||
}
|
||||
|
||||
protected void increaseAccountLevels() throws DataException {
|
||||
// We need to do this for both minters and recipients
|
||||
this.increaseAccountLevels(false, expandedAccount -> expandedAccount.mintingAccountData);
|
||||
this.increaseAccountLevels(true, expandedAccount -> expandedAccount.recipientAccountData);
|
||||
}
|
||||
|
||||
private void increaseAccountLevels(boolean isProcessingRecipients, Function<ExpandedAccount, AccountData> getAccountData) throws DataException {
|
||||
// We are only interested in accounts that are NOT already lowest level
|
||||
final List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
||||
final int maximumLevel = cumulativeBlocksByLevel.size() - 1;
|
||||
|
||||
final List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||
|
||||
// Increase blocks-minted count for all accounts
|
||||
for (int a = 0; a < expandedAccounts.size(); ++a) {
|
||||
ExpandedAccount expandedAccount = expandedAccounts.get(a);
|
||||
Set<AccountData> allUniqueExpandedAccounts = new HashSet<>();
|
||||
for (ExpandedAccount expandedAccount : expandedAccounts) {
|
||||
allUniqueExpandedAccounts.add(expandedAccount.mintingAccountData);
|
||||
|
||||
// Don't increase twice if recipient is also minter.
|
||||
if (isProcessingRecipients && expandedAccount.isRecipientAlsoMinter)
|
||||
continue;
|
||||
|
||||
AccountData accountData = getAccountData.apply(expandedAccount);
|
||||
|
||||
accountData.setBlocksMinted(accountData.getBlocksMinted() + 1);
|
||||
// repository.getAccountRepository().setMintedBlockCount(accountData); int rowCount = 1; // Until HSQLDB rev 6100 is fixed
|
||||
int rowCount = repository.getAccountRepository().modifyMintedBlockCount(accountData.getAddress(), +1);
|
||||
LOGGER.trace(() -> String.format("Block minter %s up to %d minted block%s (rowCount: %d)", accountData.getAddress(), accountData.getBlocksMinted(), (accountData.getBlocksMinted() != 1 ? "s" : ""), rowCount));
|
||||
if (!expandedAccount.isRecipientAlsoMinter)
|
||||
allUniqueExpandedAccounts.add(expandedAccount.recipientAccountData);
|
||||
}
|
||||
|
||||
// We are only interested in accounts that are NOT already highest level
|
||||
final int maximumLevel = cumulativeBlocksByLevel.size() - 1;
|
||||
List<ExpandedAccount> candidateAccounts = expandedAccounts.stream().filter(expandedAccount -> getAccountData.apply(expandedAccount).getLevel() < maximumLevel).collect(Collectors.toList());
|
||||
// Decrease blocks minted count for all accounts
|
||||
for (AccountData accountData : allUniqueExpandedAccounts) {
|
||||
// Adjust count locally (in Java)
|
||||
accountData.setBlocksMinted(accountData.getBlocksMinted() + 1);
|
||||
|
||||
for (int c = 0; c < candidateAccounts.size(); ++c) {
|
||||
ExpandedAccount expandedAccount = candidateAccounts.get(c);
|
||||
final AccountData accountData = getAccountData.apply(expandedAccount);
|
||||
int rowCount = repository.getAccountRepository().modifyMintedBlockCount(accountData.getAddress(), +1);
|
||||
LOGGER.trace(() -> String.format("Block minter %s up to %d minted block%s (rowCount: %d)", accountData.getAddress(), accountData.getBlocksMinted(), (accountData.getBlocksMinted() != 1 ? "s" : ""), rowCount));
|
||||
|
||||
final int effectiveBlocksMinted = accountData.getBlocksMinted() + accountData.getBlocksMintedAdjustment();
|
||||
|
||||
for (int newLevel = maximumLevel; newLevel > 0; --newLevel)
|
||||
for (int newLevel = maximumLevel; newLevel >= 0; --newLevel)
|
||||
if (effectiveBlocksMinted >= cumulativeBlocksByLevel.get(newLevel)) {
|
||||
if (newLevel > accountData.getLevel()) {
|
||||
// Account has increased in level!
|
||||
@ -1592,38 +1582,27 @@ public class Block {
|
||||
}
|
||||
|
||||
protected void decreaseAccountLevels() throws DataException {
|
||||
// We need to do this for both minters and recipients
|
||||
this.decreaseAccountLevels(false, expandedAccount -> expandedAccount.mintingAccountData);
|
||||
this.decreaseAccountLevels(true, expandedAccount -> expandedAccount.recipientAccountData);
|
||||
}
|
||||
|
||||
private void decreaseAccountLevels(boolean isProcessingRecipients, Function<ExpandedAccount, AccountData> getAccountData) throws DataException {
|
||||
// We are only interested in accounts that are NOT already lowest level
|
||||
final List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
||||
final int maximumLevel = cumulativeBlocksByLevel.size() - 1;
|
||||
|
||||
final List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
|
||||
|
||||
// Decrease blocks minted count for all accounts
|
||||
for (int a = 0; a < expandedAccounts.size(); ++a) {
|
||||
ExpandedAccount expandedAccount = expandedAccounts.get(a);
|
||||
Set<AccountData> allUniqueExpandedAccounts = new HashSet<>();
|
||||
for (ExpandedAccount expandedAccount : expandedAccounts) {
|
||||
allUniqueExpandedAccounts.add(expandedAccount.mintingAccountData);
|
||||
|
||||
// Don't decrease twice if recipient is also minter.
|
||||
if (isProcessingRecipients && expandedAccount.isRecipientAlsoMinter)
|
||||
continue;
|
||||
|
||||
AccountData accountData = getAccountData.apply(expandedAccount);
|
||||
|
||||
accountData.setBlocksMinted(accountData.getBlocksMinted() - 1);
|
||||
// repository.getAccountRepository().setMintedBlockCount(accountData); int rowCount = 1; // Until HSQLDB rev 6100 is fixed
|
||||
int rowCount = repository.getAccountRepository().modifyMintedBlockCount(accountData.getAddress(), -1);
|
||||
LOGGER.trace(() -> String.format("Block minter %s down to %d minted block%s (rowCount: %d)", accountData.getAddress(), accountData.getBlocksMinted(), (accountData.getBlocksMinted() != 1 ? "s" : ""), rowCount));
|
||||
if (!expandedAccount.isRecipientAlsoMinter)
|
||||
allUniqueExpandedAccounts.add(expandedAccount.recipientAccountData);
|
||||
}
|
||||
|
||||
// We are only interested in accounts that are NOT already lowest level
|
||||
final int maximumLevel = cumulativeBlocksByLevel.size() - 1;
|
||||
List<ExpandedAccount> candidateAccounts = expandedAccounts.stream().filter(expandedAccount -> getAccountData.apply(expandedAccount).getLevel() > 0).collect(Collectors.toList());
|
||||
// Decrease blocks minted count for all accounts
|
||||
for (AccountData accountData : allUniqueExpandedAccounts) {
|
||||
// Adjust count locally (in Java)
|
||||
accountData.setBlocksMinted(accountData.getBlocksMinted() - 1);
|
||||
|
||||
for (int c = 0; c < candidateAccounts.size(); ++c) {
|
||||
ExpandedAccount expandedAccount = candidateAccounts.get(c);
|
||||
final AccountData accountData = getAccountData.apply(expandedAccount);
|
||||
int rowCount = repository.getAccountRepository().modifyMintedBlockCount(accountData.getAddress(), -1);
|
||||
LOGGER.trace(() -> String.format("Block minter %s down to %d minted block%s (rowCount: %d)", accountData.getAddress(), accountData.getBlocksMinted(), (accountData.getBlocksMinted() != 1 ? "s" : ""), rowCount));
|
||||
|
||||
final int effectiveBlocksMinted = accountData.getBlocksMinted() + accountData.getBlocksMintedAdjustment();
|
||||
|
||||
|
@ -8,6 +8,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.block.BlockMinter;
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.data.account.RewardShareData;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
@ -59,13 +60,45 @@ public class BlocksMintedCountTests extends Common {
|
||||
}
|
||||
}
|
||||
|
||||
private void testRewardShare(Repository repository, PrivateKeyAccount mintingAccount, int aliceDelta, int bobDelta) throws DataException {
|
||||
@Test
|
||||
public void testMixedShares() throws DataException {
|
||||
final int sharePercent = 12_80;
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Fetch usual minting account
|
||||
PrivateKeyAccount mintingAccount = Common.getTestAccount(repository, "alice-reward-share");
|
||||
|
||||
// Create reward-share
|
||||
byte[] testRewardSharePrivateKey = AccountUtils.rewardShare(repository, "alice", "bob", sharePercent);
|
||||
PrivateKeyAccount testRewardShareAccount = new PrivateKeyAccount(repository, testRewardSharePrivateKey);
|
||||
|
||||
// Confirm reward-share info set correctly
|
||||
RewardShareData testRewardShareData = repository.getAccountRepository().getRewardShare(testRewardShareAccount.getPublicKey());
|
||||
assertNotNull(testRewardShareData);
|
||||
|
||||
// Create signed timestamps
|
||||
Controller.getInstance().ensureTestingAccountsOnline(mintingAccount, testRewardShareAccount);
|
||||
|
||||
// Even though Alice features in two online reward-shares, she should only gain +1 blocksMinted
|
||||
// Bob only features in one online reward-share, so should also only gain +1 blocksMinted
|
||||
testRewardShareRetainingTimestamps(repository, testRewardShareAccount, +1, +1);
|
||||
}
|
||||
}
|
||||
|
||||
private void testRewardShare(Repository repository, PrivateKeyAccount testRewardShareAccount, int aliceDelta, int bobDelta) throws DataException {
|
||||
// Create signed timestamps
|
||||
Controller.getInstance().ensureTestingAccountsOnline(testRewardShareAccount);
|
||||
|
||||
testRewardShareRetainingTimestamps(repository, testRewardShareAccount, aliceDelta, bobDelta);
|
||||
}
|
||||
|
||||
private void testRewardShareRetainingTimestamps(Repository repository, PrivateKeyAccount mintingAccount, int aliceDelta, int bobDelta) throws DataException {
|
||||
// Fetch pre-mint blocks minted counts
|
||||
int alicePreMintCount = getBlocksMinted(repository, "alice");
|
||||
int bobPreMintCount = getBlocksMinted(repository, "bob");
|
||||
|
||||
// Mint another block
|
||||
BlockMinter.mintTestingBlock(repository, mintingAccount);
|
||||
BlockMinter.mintTestingBlockRetainingTimestamps(repository, mintingAccount);
|
||||
|
||||
// Fetch post-mint blocks minted counts
|
||||
int alicePostMintCount = getBlocksMinted(repository, "alice");
|
||||
|
Loading…
Reference in New Issue
Block a user