Fix for Block not correctly adjusting accounts' blocksMinted values.

Added BlocksMintedCountTests to cover above.
This commit is contained in:
catbref 2020-05-05 16:10:54 +01:00
parent 0cc9cd728e
commit d2559f36ce
2 changed files with 102 additions and 12 deletions

View File

@ -12,7 +12,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
@ -139,7 +138,6 @@ public class Block {
private final Account recipientAccount;
private final AccountData recipientAccountData;
private final boolean isRecipientFounder;
ExpandedAccount(Repository repository, int accountIndex) throws DataException {
this.repository = repository;
@ -155,12 +153,10 @@ public class Block {
// Self-share: minter is also recipient
this.recipientAccount = this.mintingAccount;
this.recipientAccountData = this.mintingAccountData;
this.isRecipientFounder = this.isMinterFounder;
} else {
// Recipient differs from minter
this.recipientAccount = new Account(repository, this.rewardShareData.getRecipient());
this.recipientAccountData = repository.getAccountRepository().getAccount(this.recipientAccount.getAddress());
this.isRecipientFounder = Account.isFounder(recipientAccountData.getFlags());
}
}
@ -1273,14 +1269,13 @@ public class Block {
protected void increaseAccountLevels() throws DataException {
// We need to do this for both minters and recipients
this.increaseAccountLevels(expandedAccount -> expandedAccount.isMinterFounder, expandedAccount -> expandedAccount.mintingAccountData);
this.increaseAccountLevels(expandedAccount -> expandedAccount.isRecipientFounder, expandedAccount -> expandedAccount.recipientAccountData);
this.increaseAccountLevels(false, expandedAccount -> expandedAccount.mintingAccountData);
this.increaseAccountLevels(true, expandedAccount -> expandedAccount.recipientAccountData);
}
private void increaseAccountLevels(Predicate<ExpandedAccount> isFounder, Function<ExpandedAccount, AccountData> getAccountData) throws DataException {
private void increaseAccountLevels(boolean isProcessingRecipients, Function<ExpandedAccount, AccountData> getAccountData) throws DataException {
final List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
final List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
final boolean isProcessingRecipients = getAccountData.apply(expandedAccounts.get(0)) == expandedAccounts.get(0).recipientAccountData;
// Increase blocks-minted count for all accounts
for (int a = 0; a < expandedAccounts.size(); ++a) {
@ -1591,14 +1586,13 @@ public class Block {
protected void decreaseAccountLevels() throws DataException {
// We need to do this for both minters and recipients
this.decreaseAccountLevels(expandedAccount -> expandedAccount.isMinterFounder, expandedAccount -> expandedAccount.mintingAccountData);
this.decreaseAccountLevels(expandedAccount -> expandedAccount.isRecipientFounder, expandedAccount -> expandedAccount.recipientAccountData);
this.decreaseAccountLevels(false, expandedAccount -> expandedAccount.mintingAccountData);
this.decreaseAccountLevels(true, expandedAccount -> expandedAccount.recipientAccountData);
}
private void decreaseAccountLevels(Predicate<ExpandedAccount> isFounder, Function<ExpandedAccount, AccountData> getAccountData) throws DataException {
private void decreaseAccountLevels(boolean isProcessingRecipients, Function<ExpandedAccount, AccountData> getAccountData) throws DataException {
final List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
final List<ExpandedAccount> expandedAccounts = this.getExpandedAccounts();
final boolean isProcessingRecipients = getAccountData.apply(expandedAccounts.get(0)) == expandedAccounts.get(0).recipientAccountData;
// Decrease blocks minted count for all accounts
for (int a = 0; a < expandedAccounts.size(); ++a) {

View File

@ -0,0 +1,96 @@
package org.qortal.test.minting;
import static org.junit.Assert.*;
import java.math.BigDecimal;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.block.BlockMinter;
import org.qortal.data.account.RewardShareData;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.test.common.AccountUtils;
import org.qortal.test.common.BlockUtils;
import org.qortal.test.common.Common;
import org.qortal.test.common.TestAccount;
public class BlocksMintedCountTests extends Common {
@Before
public void beforeTest() throws DataException {
Common.useDefaultSettings();
}
@After
public void afterTest() throws DataException {
Common.orphanCheck();
}
@Test
public void testNonSelfShare() throws DataException {
final BigDecimal sharePercent = new BigDecimal("12.8");
try (final Repository repository = RepositoryManager.getRepository()) {
// 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);
testRewardShare(repository, testRewardShareAccount, +1, +1);
}
}
@Test
public void testSelfShare() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount testRewardShareAccount = Common.getTestAccount(repository, "alice-reward-share");
// Confirm reward-share exists
RewardShareData testRewardShareData = repository.getAccountRepository().getRewardShare(testRewardShareAccount.getPublicKey());
assertNotNull(testRewardShareData);
testRewardShare(repository, testRewardShareAccount, +1, 0);
}
}
private void testRewardShare(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);
// Fetch post-mint blocks minted counts
int alicePostMintCount = getBlocksMinted(repository, "alice");
int bobPostMintCount = getBlocksMinted(repository, "bob");
// Check both accounts
assertEquals("Alice's post-mint blocks-minted count incorrect", alicePreMintCount + aliceDelta, alicePostMintCount);
assertEquals("Bob's post-mint blocks-minted count incorrect", bobPreMintCount + bobDelta, bobPostMintCount);
// Orphan latest block
BlockUtils.orphanLastBlock(repository);
// Fetch post-orphan blocks minted counts
int alicePostOrphanCount = getBlocksMinted(repository, "alice");
int bobPostOrphanCount = getBlocksMinted(repository, "bob");
// Check blocks minted counts reverted correctly
assertEquals("Alice's post-orphan blocks-minted count incorrect", alicePreMintCount, alicePostOrphanCount);
assertEquals("Bob's post-orphan blocks-minted count incorrect", bobPreMintCount, bobPostOrphanCount);
}
private int getBlocksMinted(Repository repository, String name) throws DataException {
TestAccount testAccount = Common.getTestAccount(repository, name);
return repository.getAccountRepository().getAccount(testAccount.getAddress()).getBlocksMinted();
}
}