|
|
|
@ -336,4 +336,457 @@ public class RewardTests extends Common {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Test rewards for level 1 and 2 accounts both pre and post the shareBinFix, including orphaning back through the feature trigger block */
|
|
|
|
|
@Test
|
|
|
|
|
public void testLevel1And2Rewards() throws DataException {
|
|
|
|
|
Common.useSettings("test-settings-v2-reward-levels.json");
|
|
|
|
|
|
|
|
|
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
|
|
|
|
|
|
|
|
|
List<PrivateKeyAccount> mintingAndOnlineAccounts = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// Alice self share online
|
|
|
|
|
PrivateKeyAccount aliceSelfShare = Common.getTestAccount(repository, "alice-reward-share");
|
|
|
|
|
mintingAndOnlineAccounts.add(aliceSelfShare);
|
|
|
|
|
|
|
|
|
|
// Bob self-share NOT online
|
|
|
|
|
|
|
|
|
|
// Chloe self share online
|
|
|
|
|
byte[] chloeRewardSharePrivateKey = AccountUtils.rewardShare(repository, "chloe", "chloe", 0);
|
|
|
|
|
PrivateKeyAccount chloeRewardShareAccount = new PrivateKeyAccount(repository, chloeRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(chloeRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Dilbert self share online
|
|
|
|
|
byte[] dilbertRewardSharePrivateKey = AccountUtils.rewardShare(repository, "dilbert", "dilbert", 0);
|
|
|
|
|
PrivateKeyAccount dilbertRewardShareAccount = new PrivateKeyAccount(repository, dilbertRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(dilbertRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Mint a couple of blocks so that we are able to orphan them later
|
|
|
|
|
for (int i=0; i<2; i++)
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure that the levels are as we expect
|
|
|
|
|
assertEquals(1, (int) Common.getTestAccount(repository, "alice").getLevel());
|
|
|
|
|
assertEquals(1, (int) Common.getTestAccount(repository, "bob").getLevel());
|
|
|
|
|
assertEquals(1, (int) Common.getTestAccount(repository, "chloe").getLevel());
|
|
|
|
|
assertEquals(2, (int) Common.getTestAccount(repository, "dilbert").getLevel());
|
|
|
|
|
|
|
|
|
|
// Ensure that only Alice is a founder
|
|
|
|
|
assertEquals(1, getFlags(repository, "alice"));
|
|
|
|
|
assertEquals(0, getFlags(repository, "bob"));
|
|
|
|
|
assertEquals(0, getFlags(repository, "chloe"));
|
|
|
|
|
assertEquals(0, getFlags(repository, "dilbert"));
|
|
|
|
|
|
|
|
|
|
// Now that everyone is at level 1 or 2, we can capture initial balances
|
|
|
|
|
Map<String, Map<Long, Long>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT, Asset.LEGACY_QORA, Asset.QORT_FROM_QORA);
|
|
|
|
|
final long aliceInitialBalance = initialBalances.get("alice").get(Asset.QORT);
|
|
|
|
|
final long bobInitialBalance = initialBalances.get("bob").get(Asset.QORT);
|
|
|
|
|
final long chloeInitialBalance = initialBalances.get("chloe").get(Asset.QORT);
|
|
|
|
|
final long dilbertInitialBalance = initialBalances.get("dilbert").get(Asset.QORT);
|
|
|
|
|
|
|
|
|
|
// Mint a block
|
|
|
|
|
final long blockReward = BlockUtils.getNextBlockReward(repository);
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure we are at the correct height and block reward value
|
|
|
|
|
assertEquals(6, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
|
|
|
|
assertEquals(10000000000L, blockReward);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Alice, Chloe, and Dilbert are 'online'. Bob is offline.
|
|
|
|
|
* Chloe is level 1, Dilbert is level 2.
|
|
|
|
|
* One founder online (Alice, who is also level 1).
|
|
|
|
|
* No legacy QORA holders.
|
|
|
|
|
*
|
|
|
|
|
* Chloe and Dilbert should receive equal shares of the 5% block reward for Level 1 and 2
|
|
|
|
|
* Alice should receive the remainder (95%)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// We are after the shareBinFix feature trigger, so we expect level 1 and 2 to share the same reward (5%)
|
|
|
|
|
final int level1And2SharePercent = 5_00; // 5%
|
|
|
|
|
final long level1And2ShareAmount = (blockReward * level1And2SharePercent) / 100L / 100L;
|
|
|
|
|
final long expectedReward = level1And2ShareAmount / 2; // The reward is split between Chloe and Dilbert
|
|
|
|
|
final long expectedFounderReward = blockReward - level1And2ShareAmount; // Alice should receive the remainder
|
|
|
|
|
|
|
|
|
|
// Validate the balances to ensure that the correct post-shareBinFix distribution is being applied
|
|
|
|
|
assertEquals(500000000, level1And2ShareAmount);
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance+expectedFounderReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance+expectedReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance+expectedReward);
|
|
|
|
|
|
|
|
|
|
// Now orphan the latest block. This brings us to the threshold of the shareBinFix feature trigger.
|
|
|
|
|
BlockUtils.orphanBlocks(repository, 1);
|
|
|
|
|
assertEquals(5, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
|
|
|
|
|
|
|
|
|
// Ensure the latest post-fix block rewards have been subtracted and they have returned to their initial values
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance);
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance);
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance);
|
|
|
|
|
|
|
|
|
|
// Orphan another block. This time, the block that was orphaned was prior to the shareBinFix feature trigger.
|
|
|
|
|
BlockUtils.orphanBlocks(repository, 1);
|
|
|
|
|
assertEquals(4, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
|
|
|
|
|
|
|
|
|
// Prior to the fix, the levels were incorrectly grouped
|
|
|
|
|
// Chloe should receive 100% of the level 1 reward, and Dilbert should receive 100% of the level 2+3 reward
|
|
|
|
|
final int level1SharePercent = 5_00; // 5%
|
|
|
|
|
final int level2And3SharePercent = 10_00; // 10%
|
|
|
|
|
final long level1ShareAmountBeforeFix = (blockReward * level1SharePercent) / 100L / 100L;
|
|
|
|
|
final long level2And3ShareAmountBeforeFix = (blockReward * level2And3SharePercent) / 100L / 100L;
|
|
|
|
|
final long expectedFounderRewardBeforeFix = blockReward - level1ShareAmountBeforeFix - level2And3ShareAmountBeforeFix; // Alice should receive the remainder
|
|
|
|
|
|
|
|
|
|
// Validate the share amounts and balances
|
|
|
|
|
assertEquals(500000000, level1ShareAmountBeforeFix);
|
|
|
|
|
assertEquals(1000000000, level2And3ShareAmountBeforeFix);
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance-expectedFounderRewardBeforeFix);
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance-level1ShareAmountBeforeFix);
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance-level2And3ShareAmountBeforeFix);
|
|
|
|
|
|
|
|
|
|
// Orphan the latest block one last time
|
|
|
|
|
BlockUtils.orphanBlocks(repository, 1);
|
|
|
|
|
assertEquals(3, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
|
|
|
|
|
|
|
|
|
// Validate balances
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance-(expectedFounderRewardBeforeFix*2));
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance-(level1ShareAmountBeforeFix*2));
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance-(level2And3ShareAmountBeforeFix*2));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Test rewards for level 3 and 4 accounts */
|
|
|
|
|
@Test
|
|
|
|
|
public void testLevel3And4Rewards() throws DataException {
|
|
|
|
|
Common.useSettings("test-settings-v2-reward-levels.json");
|
|
|
|
|
|
|
|
|
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
|
|
|
|
|
|
|
|
|
List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
|
|
|
|
List<PrivateKeyAccount> mintingAndOnlineAccounts = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// Alice self share online
|
|
|
|
|
PrivateKeyAccount aliceSelfShare = Common.getTestAccount(repository, "alice-reward-share");
|
|
|
|
|
mintingAndOnlineAccounts.add(aliceSelfShare);
|
|
|
|
|
|
|
|
|
|
// Bob self-share online
|
|
|
|
|
byte[] bobRewardSharePrivateKey = AccountUtils.rewardShare(repository, "bob", "bob", 0);
|
|
|
|
|
PrivateKeyAccount bobRewardShareAccount = new PrivateKeyAccount(repository, bobRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(bobRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Chloe self share online
|
|
|
|
|
byte[] chloeRewardSharePrivateKey = AccountUtils.rewardShare(repository, "chloe", "chloe", 0);
|
|
|
|
|
PrivateKeyAccount chloeRewardShareAccount = new PrivateKeyAccount(repository, chloeRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(chloeRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Dilbert self share online
|
|
|
|
|
byte[] dilbertRewardSharePrivateKey = AccountUtils.rewardShare(repository, "dilbert", "dilbert", 0);
|
|
|
|
|
PrivateKeyAccount dilbertRewardShareAccount = new PrivateKeyAccount(repository, dilbertRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(dilbertRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Mint enough blocks to bump testAccount levels to 3 and 4
|
|
|
|
|
final int minterBlocksNeeded = cumulativeBlocksByLevel.get(4) - 20; // 20 blocks before level 4, so that the test accounts reach the correct levels
|
|
|
|
|
for (int bc = 0; bc < minterBlocksNeeded; ++bc)
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure that the levels are as we expect
|
|
|
|
|
assertEquals(3, (int) Common.getTestAccount(repository, "alice").getLevel());
|
|
|
|
|
assertEquals(3, (int) Common.getTestAccount(repository, "bob").getLevel());
|
|
|
|
|
assertEquals(3, (int) Common.getTestAccount(repository, "chloe").getLevel());
|
|
|
|
|
assertEquals(4, (int) Common.getTestAccount(repository, "dilbert").getLevel());
|
|
|
|
|
|
|
|
|
|
// Now that everyone is at level 3 or 4, we can capture initial balances
|
|
|
|
|
Map<String, Map<Long, Long>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT, Asset.LEGACY_QORA, Asset.QORT_FROM_QORA);
|
|
|
|
|
final long aliceInitialBalance = initialBalances.get("alice").get(Asset.QORT);
|
|
|
|
|
final long bobInitialBalance = initialBalances.get("bob").get(Asset.QORT);
|
|
|
|
|
final long chloeInitialBalance = initialBalances.get("chloe").get(Asset.QORT);
|
|
|
|
|
final long dilbertInitialBalance = initialBalances.get("dilbert").get(Asset.QORT);
|
|
|
|
|
|
|
|
|
|
// Mint a block
|
|
|
|
|
final long blockReward = BlockUtils.getNextBlockReward(repository);
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure we are using the correct block reward value
|
|
|
|
|
assertEquals(100000000L, blockReward);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Alice, Bob, Chloe, and Dilbert are 'online'.
|
|
|
|
|
* Bob and Chloe are level 3; Dilbert is level 4.
|
|
|
|
|
* One founder online (Alice, who is also level 3).
|
|
|
|
|
* No legacy QORA holders.
|
|
|
|
|
*
|
|
|
|
|
* Chloe, Bob and Dilbert should receive equal shares of the 10% block reward for level 3 and 4
|
|
|
|
|
* Alice should receive the remainder (90%)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// We are after the shareBinFix feature trigger, so we expect level 3 and 4 to share the same reward (10%)
|
|
|
|
|
final int level3And4SharePercent = 10_00; // 10%
|
|
|
|
|
final long level3And4ShareAmount = (blockReward * level3And4SharePercent) / 100L / 100L;
|
|
|
|
|
final long expectedReward = level3And4ShareAmount / 3; // The reward is split between Bob, Chloe, and Dilbert
|
|
|
|
|
final long expectedFounderReward = blockReward - level3And4ShareAmount; // Alice should receive the remainder
|
|
|
|
|
|
|
|
|
|
// Validate the balances to ensure that the correct post-shareBinFix distribution is being applied
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance+expectedFounderReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance+expectedReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance+expectedReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance+expectedReward);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Test rewards for level 5 and 6 accounts */
|
|
|
|
|
@Test
|
|
|
|
|
public void testLevel5And6Rewards() throws DataException {
|
|
|
|
|
Common.useSettings("test-settings-v2-reward-levels.json");
|
|
|
|
|
|
|
|
|
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
|
|
|
|
|
|
|
|
|
List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
|
|
|
|
List<PrivateKeyAccount> mintingAndOnlineAccounts = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// Alice self share online
|
|
|
|
|
PrivateKeyAccount aliceSelfShare = Common.getTestAccount(repository, "alice-reward-share");
|
|
|
|
|
mintingAndOnlineAccounts.add(aliceSelfShare);
|
|
|
|
|
|
|
|
|
|
// Bob self-share not initially online
|
|
|
|
|
|
|
|
|
|
// Chloe self share online
|
|
|
|
|
byte[] chloeRewardSharePrivateKey = AccountUtils.rewardShare(repository, "chloe", "chloe", 0);
|
|
|
|
|
PrivateKeyAccount chloeRewardShareAccount = new PrivateKeyAccount(repository, chloeRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(chloeRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Dilbert self share online
|
|
|
|
|
byte[] dilbertRewardSharePrivateKey = AccountUtils.rewardShare(repository, "dilbert", "dilbert", 0);
|
|
|
|
|
PrivateKeyAccount dilbertRewardShareAccount = new PrivateKeyAccount(repository, dilbertRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(dilbertRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Mint enough blocks to bump testAccount levels to 5 and 6
|
|
|
|
|
final int minterBlocksNeeded = cumulativeBlocksByLevel.get(6) - 20; // 20 blocks before level 6, so that the test accounts reach the correct levels
|
|
|
|
|
for (int bc = 0; bc < minterBlocksNeeded; ++bc)
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Bob self-share now comes online
|
|
|
|
|
byte[] bobRewardSharePrivateKey = AccountUtils.rewardShare(repository, "bob", "bob", 0);
|
|
|
|
|
PrivateKeyAccount bobRewardShareAccount = new PrivateKeyAccount(repository, bobRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(bobRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Ensure that the levels are as we expect
|
|
|
|
|
assertEquals(5, (int) Common.getTestAccount(repository, "alice").getLevel());
|
|
|
|
|
assertEquals(1, (int) Common.getTestAccount(repository, "bob").getLevel());
|
|
|
|
|
assertEquals(5, (int) Common.getTestAccount(repository, "chloe").getLevel());
|
|
|
|
|
assertEquals(6, (int) Common.getTestAccount(repository, "dilbert").getLevel());
|
|
|
|
|
|
|
|
|
|
// Now that everyone is at level 5 or 6 (except Bob who has only just started minting, so is at level 1), we can capture initial balances
|
|
|
|
|
Map<String, Map<Long, Long>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT, Asset.LEGACY_QORA, Asset.QORT_FROM_QORA);
|
|
|
|
|
final long aliceInitialBalance = initialBalances.get("alice").get(Asset.QORT);
|
|
|
|
|
final long bobInitialBalance = initialBalances.get("bob").get(Asset.QORT);
|
|
|
|
|
final long chloeInitialBalance = initialBalances.get("chloe").get(Asset.QORT);
|
|
|
|
|
final long dilbertInitialBalance = initialBalances.get("dilbert").get(Asset.QORT);
|
|
|
|
|
|
|
|
|
|
// Mint a block
|
|
|
|
|
final long blockReward = BlockUtils.getNextBlockReward(repository);
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure we are using the correct block reward value
|
|
|
|
|
assertEquals(100000000L, blockReward);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Alice, Bob, Chloe, and Dilbert are 'online'.
|
|
|
|
|
* Bob is level 1; Chloe is level 5; Dilbert is level 6.
|
|
|
|
|
* One founder online (Alice, who is also level 5).
|
|
|
|
|
* No legacy QORA holders.
|
|
|
|
|
*
|
|
|
|
|
* Chloe and Dilbert should receive equal shares of the 15% block reward for level 5 and 6
|
|
|
|
|
* Bob should receive all of the level 1 and 2 reward (5%)
|
|
|
|
|
* Alice should receive the remainder (80%)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// We are after the shareBinFix feature trigger, so we expect level 5 and 6 to share the same reward (15%)
|
|
|
|
|
final int level1And2SharePercent = 5_00; // 5%
|
|
|
|
|
final int level5And6SharePercent = 15_00; // 10%
|
|
|
|
|
final long level1And2ShareAmount = (blockReward * level1And2SharePercent) / 100L / 100L;
|
|
|
|
|
final long level5And6ShareAmount = (blockReward * level5And6SharePercent) / 100L / 100L;
|
|
|
|
|
final long expectedLevel1And2Reward = level1And2ShareAmount; // The reward is given entirely to Bob
|
|
|
|
|
final long expectedLevel5And6Reward = level5And6ShareAmount / 2; // The reward is split between Chloe and Dilbert
|
|
|
|
|
final long expectedFounderReward = blockReward - level1And2ShareAmount - level5And6ShareAmount; // Alice should receive the remainder
|
|
|
|
|
|
|
|
|
|
// Validate the balances to ensure that the correct post-shareBinFix distribution is being applied
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance+expectedFounderReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance+expectedLevel1And2Reward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance+expectedLevel5And6Reward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance+expectedLevel5And6Reward);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Test rewards for level 7 and 8 accounts */
|
|
|
|
|
@Test
|
|
|
|
|
public void testLevel7And8Rewards() throws DataException {
|
|
|
|
|
Common.useSettings("test-settings-v2-reward-levels.json");
|
|
|
|
|
|
|
|
|
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
|
|
|
|
|
|
|
|
|
List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
|
|
|
|
List<PrivateKeyAccount> mintingAndOnlineAccounts = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// Alice self share online
|
|
|
|
|
PrivateKeyAccount aliceSelfShare = Common.getTestAccount(repository, "alice-reward-share");
|
|
|
|
|
mintingAndOnlineAccounts.add(aliceSelfShare);
|
|
|
|
|
|
|
|
|
|
// Bob self-share NOT online
|
|
|
|
|
|
|
|
|
|
// Chloe self share online
|
|
|
|
|
byte[] chloeRewardSharePrivateKey = AccountUtils.rewardShare(repository, "chloe", "chloe", 0);
|
|
|
|
|
PrivateKeyAccount chloeRewardShareAccount = new PrivateKeyAccount(repository, chloeRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(chloeRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Dilbert self share online
|
|
|
|
|
byte[] dilbertRewardSharePrivateKey = AccountUtils.rewardShare(repository, "dilbert", "dilbert", 0);
|
|
|
|
|
PrivateKeyAccount dilbertRewardShareAccount = new PrivateKeyAccount(repository, dilbertRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(dilbertRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Mint enough blocks to bump testAccount levels to 7 and 8
|
|
|
|
|
final int minterBlocksNeeded = cumulativeBlocksByLevel.get(8) - 20; // 20 blocks before level 8, so that the test accounts reach the correct levels
|
|
|
|
|
for (int bc = 0; bc < minterBlocksNeeded; ++bc)
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure that the levels are as we expect
|
|
|
|
|
assertEquals(7, (int) Common.getTestAccount(repository, "alice").getLevel());
|
|
|
|
|
assertEquals(1, (int) Common.getTestAccount(repository, "bob").getLevel());
|
|
|
|
|
assertEquals(7, (int) Common.getTestAccount(repository, "chloe").getLevel());
|
|
|
|
|
assertEquals(8, (int) Common.getTestAccount(repository, "dilbert").getLevel());
|
|
|
|
|
|
|
|
|
|
// Now that everyone is at level 7 or 8 (except Bob who has only just started minting, so is at level 1), we can capture initial balances
|
|
|
|
|
Map<String, Map<Long, Long>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT, Asset.LEGACY_QORA, Asset.QORT_FROM_QORA);
|
|
|
|
|
final long aliceInitialBalance = initialBalances.get("alice").get(Asset.QORT);
|
|
|
|
|
final long bobInitialBalance = initialBalances.get("bob").get(Asset.QORT);
|
|
|
|
|
final long chloeInitialBalance = initialBalances.get("chloe").get(Asset.QORT);
|
|
|
|
|
final long dilbertInitialBalance = initialBalances.get("dilbert").get(Asset.QORT);
|
|
|
|
|
|
|
|
|
|
// Mint a block
|
|
|
|
|
final long blockReward = BlockUtils.getNextBlockReward(repository);
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure we are using the correct block reward value
|
|
|
|
|
assertEquals(100000000L, blockReward);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Alice, Chloe, and Dilbert are 'online'.
|
|
|
|
|
* Chloe is level 7; Dilbert is level 8.
|
|
|
|
|
* One founder online (Alice, who is also level 7).
|
|
|
|
|
* No legacy QORA holders.
|
|
|
|
|
*
|
|
|
|
|
* Chloe and Dilbert should receive equal shares of the 20% block reward for level 7 and 8
|
|
|
|
|
* Alice should receive the remainder (80%)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// We are after the shareBinFix feature trigger, so we expect level 7 and 8 to share the same reward (20%)
|
|
|
|
|
final int level7And8SharePercent = 20_00; // 20%
|
|
|
|
|
final long level7And8ShareAmount = (blockReward * level7And8SharePercent) / 100L / 100L;
|
|
|
|
|
final long expectedLevel7And8Reward = level7And8ShareAmount / 2; // The reward is split between Chloe and Dilbert
|
|
|
|
|
final long expectedFounderReward = blockReward - level7And8ShareAmount; // Alice should receive the remainder
|
|
|
|
|
|
|
|
|
|
// Validate the balances to ensure that the correct post-shareBinFix distribution is being applied
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance+expectedFounderReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance+expectedLevel7And8Reward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance+expectedLevel7And8Reward);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Test rewards for level 9 and 10 accounts */
|
|
|
|
|
@Test
|
|
|
|
|
public void testLevel9And10Rewards() throws DataException {
|
|
|
|
|
Common.useSettings("test-settings-v2-reward-levels.json");
|
|
|
|
|
|
|
|
|
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
|
|
|
|
|
|
|
|
|
List<Integer> cumulativeBlocksByLevel = BlockChain.getInstance().getCumulativeBlocksByLevel();
|
|
|
|
|
List<PrivateKeyAccount> mintingAndOnlineAccounts = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// Alice self share online
|
|
|
|
|
PrivateKeyAccount aliceSelfShare = Common.getTestAccount(repository, "alice-reward-share");
|
|
|
|
|
mintingAndOnlineAccounts.add(aliceSelfShare);
|
|
|
|
|
|
|
|
|
|
// Bob self-share not initially online
|
|
|
|
|
|
|
|
|
|
// Chloe self share online
|
|
|
|
|
byte[] chloeRewardSharePrivateKey = AccountUtils.rewardShare(repository, "chloe", "chloe", 0);
|
|
|
|
|
PrivateKeyAccount chloeRewardShareAccount = new PrivateKeyAccount(repository, chloeRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(chloeRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Dilbert self share online
|
|
|
|
|
byte[] dilbertRewardSharePrivateKey = AccountUtils.rewardShare(repository, "dilbert", "dilbert", 0);
|
|
|
|
|
PrivateKeyAccount dilbertRewardShareAccount = new PrivateKeyAccount(repository, dilbertRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(dilbertRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Mint enough blocks to bump testAccount levels to 9 and 10
|
|
|
|
|
final int minterBlocksNeeded = cumulativeBlocksByLevel.get(10) - 20; // 20 blocks before level 10, so that the test accounts reach the correct levels
|
|
|
|
|
for (int bc = 0; bc < minterBlocksNeeded; ++bc)
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Bob self-share now comes online
|
|
|
|
|
byte[] bobRewardSharePrivateKey = AccountUtils.rewardShare(repository, "bob", "bob", 0);
|
|
|
|
|
PrivateKeyAccount bobRewardShareAccount = new PrivateKeyAccount(repository, bobRewardSharePrivateKey);
|
|
|
|
|
mintingAndOnlineAccounts.add(bobRewardShareAccount);
|
|
|
|
|
|
|
|
|
|
// Ensure that the levels are as we expect
|
|
|
|
|
assertEquals(9, (int) Common.getTestAccount(repository, "alice").getLevel());
|
|
|
|
|
assertEquals(1, (int) Common.getTestAccount(repository, "bob").getLevel());
|
|
|
|
|
assertEquals(9, (int) Common.getTestAccount(repository, "chloe").getLevel());
|
|
|
|
|
assertEquals(10, (int) Common.getTestAccount(repository, "dilbert").getLevel());
|
|
|
|
|
|
|
|
|
|
// Now that everyone is at level 7 or 8 (except Bob who has only just started minting, so is at level 1), we can capture initial balances
|
|
|
|
|
Map<String, Map<Long, Long>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT, Asset.LEGACY_QORA, Asset.QORT_FROM_QORA);
|
|
|
|
|
final long aliceInitialBalance = initialBalances.get("alice").get(Asset.QORT);
|
|
|
|
|
final long bobInitialBalance = initialBalances.get("bob").get(Asset.QORT);
|
|
|
|
|
final long chloeInitialBalance = initialBalances.get("chloe").get(Asset.QORT);
|
|
|
|
|
final long dilbertInitialBalance = initialBalances.get("dilbert").get(Asset.QORT);
|
|
|
|
|
|
|
|
|
|
// Mint a block
|
|
|
|
|
final long blockReward = BlockUtils.getNextBlockReward(repository);
|
|
|
|
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
|
|
|
|
|
|
|
|
|
// Ensure we are using the correct block reward value
|
|
|
|
|
assertEquals(100000000L, blockReward);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Alice, Bob, Chloe, and Dilbert are 'online'.
|
|
|
|
|
* Bob is level 1; Chloe is level 9; Dilbert is level 10.
|
|
|
|
|
* One founder online (Alice, who is also level 9).
|
|
|
|
|
* No legacy QORA holders.
|
|
|
|
|
*
|
|
|
|
|
* Chloe and Dilbert should receive equal shares of the 25% block reward for level 9 and 10
|
|
|
|
|
* Bob should receive all of the level 1 and 2 reward (5%)
|
|
|
|
|
* Alice should receive the remainder (70%)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// We are after the shareBinFix feature trigger, so we expect level 9 and 10 to share the same reward (25%)
|
|
|
|
|
final int level1And2SharePercent = 5_00; // 5%
|
|
|
|
|
final int level9And10SharePercent = 25_00; // 25%
|
|
|
|
|
final long level1And2ShareAmount = (blockReward * level1And2SharePercent) / 100L / 100L;
|
|
|
|
|
final long level9And10ShareAmount = (blockReward * level9And10SharePercent) / 100L / 100L;
|
|
|
|
|
final long expectedLevel1And2Reward = level1And2ShareAmount; // The reward is given entirely to Bob
|
|
|
|
|
final long expectedLevel9And10Reward = level9And10ShareAmount / 2; // The reward is split between Chloe and Dilbert
|
|
|
|
|
final long expectedFounderReward = blockReward - level1And2ShareAmount - level9And10ShareAmount; // Alice should receive the remainder
|
|
|
|
|
|
|
|
|
|
// Validate the balances to ensure that the correct post-shareBinFix distribution is being applied
|
|
|
|
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance+expectedFounderReward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance+expectedLevel1And2Reward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance+expectedLevel9And10Reward);
|
|
|
|
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance+expectedLevel9And10Reward);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int getFlags(Repository repository, String name) throws DataException {
|
|
|
|
|
TestAccount testAccount = Common.getTestAccount(repository, name);
|
|
|
|
|
return repository.getAccountRepository().getAccount(testAccount.getAddress()).getFlags();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|