diff --git a/src/main/java/org/qortal/block/Block.java b/src/main/java/org/qortal/block/Block.java index f2291910..1e07f2e7 100644 --- a/src/main/java/org/qortal/block/Block.java +++ b/src/main/java/org/qortal/block/Block.java @@ -1735,7 +1735,7 @@ public class Block { for (int newLevel = maximumLevel; newLevel >= 0; --newLevel) if (effectiveBlocksMinted >= cumulativeBlocksByLevel.get(newLevel)) { - if (newLevel > accountData.getLevel()) { + if (newLevel != accountData.getLevel()) { // Account has increased in level! accountData.setLevel(newLevel); bumpedAccounts.put(accountData.getAddress(), newLevel); @@ -2141,7 +2141,7 @@ public class Block { int blocksMintedAdjustment = - (this.blockData.getHeight() > BlockChain.getInstance().getMintedBlocksAdjustmentRemovalHeight()) + (this.blockData.getHeight() -1 > BlockChain.getInstance().getMintedBlocksAdjustmentRemovalHeight()) ? 0 : @@ -2151,7 +2151,7 @@ public class Block { for (int newLevel = maximumLevel; newLevel >= 0; --newLevel) if (effectiveBlocksMinted >= cumulativeBlocksByLevel.get(newLevel)) { - if (newLevel < accountData.getLevel()) { + if (newLevel != accountData.getLevel()) { // Account has decreased in level! accountData.setLevel(newLevel); repository.getAccountRepository().setLevel(accountData); diff --git a/src/test/java/org/qortal/test/minting/BlocksMintedCountTests.java b/src/test/java/org/qortal/test/minting/BlocksMintedCountTests.java index 65a616b0..16ff354f 100644 --- a/src/test/java/org/qortal/test/minting/BlocksMintedCountTests.java +++ b/src/test/java/org/qortal/test/minting/BlocksMintedCountTests.java @@ -4,8 +4,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.qortal.account.PrivateKeyAccount; +import org.qortal.block.BlockChain; import org.qortal.controller.BlockMinter; import org.qortal.controller.OnlineAccountsManager; +import org.qortal.data.account.AccountData; import org.qortal.data.account.RewardShareData; import org.qortal.repository.DataException; import org.qortal.repository.Repository; @@ -15,8 +17,9 @@ import org.qortal.test.common.BlockUtils; import org.qortal.test.common.Common; import org.qortal.test.common.TestAccount; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import java.util.List; + +import static org.junit.Assert.*; public class BlocksMintedCountTests extends Common { @@ -85,6 +88,121 @@ public class BlocksMintedCountTests extends Common { } } + @Test + public void testLevelSetting() { + + boolean exceptionThrown = false; + + try (final Repository repository = RepositoryManager.getRepository()) { + + // get the Alice's reward share account + PrivateKeyAccount aliceMintingAccount = Common.getTestAccount(repository, "alice-reward-share"); + + // give Alice an 8 blocks minted adjustment + int blocksMintedAdjustmentForAlice = 8; + adjustMintingData(repository, "alice", blocksMintedAdjustmentForAlice); + + // Confirm reward-share exists + RewardShareData aliceRewardShareData = repository.getAccountRepository().getRewardShare(aliceMintingAccount.getPublicKey()); + assertNotNull(aliceRewardShareData); + + // mint 40 blocks + for( int i = 0; i < 40; i++ ) { + // Create signed timestamps + OnlineAccountsManager.getInstance().ensureTestingAccountsOnline(aliceMintingAccount); + + // Mint another block + BlockMinter.mintTestingBlockRetainingTimestamps(repository, aliceMintingAccount); + + // assert Alice's minting data after another block minted + assertMintingData(repository, "alice", blocksMintedAdjustmentForAlice); + + // orphan the block + BlockUtils.orphanLastBlock(repository); + + // assert the orphaning + assertMintingData(repository, "alice", blocksMintedAdjustmentForAlice); + + // mint another block to reverse the orpaning + BlockMinter.mintTestingBlockRetainingTimestamps(repository, aliceMintingAccount); + } + } + catch (DataException e) { + exceptionThrown = true; + } + + assertFalse(exceptionThrown); + } + + /** + * Assert Minting Data + * + * @param repository the data repository + * @param name the name of the minting account + * @param adjustment the blocks minted adjustment + * + * @throws DataException + */ + private static void assertMintingData(Repository repository, String name, int adjustment ) throws DataException { + + // get the test account data + TestAccount testAccount = Common.getTestAccount(repository, name); + AccountData testAccountData = repository.getAccountRepository().getAccount(testAccount.getAddress()); + + List blocksNeededByLevel = BlockChain.getInstance().getBlocksNeededByLevel(); + + // determine current height and adjustment ability + int height = repository.getBlockRepository().getBlockchainHeight(); + int adjustmentRemovalHeight = BlockChain.getInstance().getMintedBlocksAdjustmentRemovalHeight(); + boolean isAdjustingEnabled = height <= adjustmentRemovalHeight; + + // initialize loop variables + int blocksLeft; + + if( isAdjustingEnabled ) + blocksLeft = testAccountData.getBlocksMinted() + adjustment; + else + blocksLeft = testAccountData.getBlocksMinted(); + + int index = 0; + int expectedLevel = 0; + + // update expected level based on the blocks needed by level list entries + while( blocksNeededByLevel.size() > index ) { + + Integer blocksNeededByThisLevel = blocksNeededByLevel.get(index); + if( blocksNeededByThisLevel <= blocksLeft ) { + expectedLevel++; + blocksLeft -= blocksNeededByThisLevel; + } + else { + break; + } + + index++; + } + + // print and assert the expected and derived numbers + System.out.println(String.format("height = %s,expectedLevel = %s, adjustment = %s, blocksMinted = %s", height, expectedLevel, adjustment, testAccountData.getBlocksMinted()) ); + assertEquals( expectedLevel, testAccountData.getLevel() ); + } + + /** + * Adjust Minting Data + * + * @param repository the data repository + * @param name the name of the account to adjust + * @param blocksMintedAdjustment the number of blocks to adjust + * + * @throws DataException + */ + private static void adjustMintingData(Repository repository, String name, int blocksMintedAdjustment) throws DataException { + TestAccount testAccount = Common.getTestAccount(repository, name); + AccountData testAccountData = repository.getAccountRepository().getAccount(testAccount.getAddress()); + testAccountData.setBlocksMintedAdjustment(blocksMintedAdjustment); + repository.getAccountRepository().setBlocksMintedAdjustment(testAccountData); + } + private void testRewardShare(Repository repository, PrivateKeyAccount testRewardShareAccount, int aliceDelta, int bobDelta) throws DataException { // Create signed timestamps OnlineAccountsManager.getInstance().ensureTestingAccountsOnline(testRewardShareAccount); @@ -124,5 +242,4 @@ public class BlocksMintedCountTests extends Common { TestAccount testAccount = Common.getTestAccount(repository, name); return repository.getAccountRepository().getAccount(testAccount.getAddress()).getBlocksMinted(); } - } diff --git a/src/test/resources/test-chain-v2.json b/src/test/resources/test-chain-v2.json index 3bf89ab5..d7f7ea13 100644 --- a/src/test/resources/test-chain-v2.json +++ b/src/test/resources/test-chain-v2.json @@ -116,7 +116,7 @@ "nullGroupMembershipHeight": 20, "adminQueryFixHeight": 9999999999999, "multipleNamesPerAccountHeight": 10, - "mintedBlocksAdjustmentRemovalHeight": 9999999999999 + "mintedBlocksAdjustmentRemovalHeight": 27 }, "genesisInfo": { "version": 4,