mirror of
https://github.com/Qortal/qortal.git
synced 2025-06-19 06:11:20 +00:00
Merge branch 'block-reward-distribution-fix'
This commit is contained in:
commit
ea1fed2fd3
@ -176,19 +176,26 @@ public class Block {
|
|||||||
*
|
*
|
||||||
* @return account-level share "bin" from blockchain config, or null if founder / none found
|
* @return account-level share "bin" from blockchain config, or null if founder / none found
|
||||||
*/
|
*/
|
||||||
public AccountLevelShareBin getShareBin() {
|
public AccountLevelShareBin getShareBin(int blockHeight) {
|
||||||
if (this.isMinterFounder)
|
if (this.isMinterFounder)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
final int accountLevel = this.mintingAccountData.getLevel();
|
final int accountLevel = this.mintingAccountData.getLevel();
|
||||||
if (accountLevel <= 0)
|
if (accountLevel <= 0)
|
||||||
return null;
|
return null; // level 0 isn't included in any share bins
|
||||||
|
|
||||||
final AccountLevelShareBin[] shareBinsByLevel = BlockChain.getInstance().getShareBinsByAccountLevel();
|
final BlockChain blockChain = BlockChain.getInstance();
|
||||||
|
final AccountLevelShareBin[] shareBinsByLevel = blockChain.getShareBinsByAccountLevel();
|
||||||
if (accountLevel > shareBinsByLevel.length)
|
if (accountLevel > shareBinsByLevel.length)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return shareBinsByLevel[accountLevel];
|
if (blockHeight < blockChain.getShareBinFixHeight())
|
||||||
|
// Off-by-one bug still in effect
|
||||||
|
return shareBinsByLevel[accountLevel];
|
||||||
|
|
||||||
|
// level 1 stored at index 0, level 2 stored at index 1, etc.
|
||||||
|
return shareBinsByLevel[accountLevel-1];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long distribute(long accountAmount, Map<String, Long> balanceChanges) {
|
public long distribute(long accountAmount, Map<String, Long> balanceChanges) {
|
||||||
@ -1783,7 +1790,7 @@ public class Block {
|
|||||||
// Find all accounts in share bin. getShareBin() returns null for minter accounts that are also founders, so they are effectively filtered out.
|
// Find all accounts in share bin. getShareBin() returns null for minter accounts that are also founders, so they are effectively filtered out.
|
||||||
AccountLevelShareBin accountLevelShareBin = accountLevelShareBins.get(binIndex);
|
AccountLevelShareBin accountLevelShareBin = accountLevelShareBins.get(binIndex);
|
||||||
// Object reference compare is OK as all references are read-only from blockchain config.
|
// Object reference compare is OK as all references are read-only from blockchain config.
|
||||||
List<ExpandedAccount> binnedAccounts = expandedAccounts.stream().filter(accountInfo -> accountInfo.getShareBin() == accountLevelShareBin).collect(Collectors.toList());
|
List<ExpandedAccount> binnedAccounts = expandedAccounts.stream().filter(accountInfo -> accountInfo.getShareBin(this.blockData.getHeight()) == accountLevelShareBin).collect(Collectors.toList());
|
||||||
|
|
||||||
// No online accounts in this bin? Skip to next one
|
// No online accounts in this bin? Skip to next one
|
||||||
if (binnedAccounts.isEmpty())
|
if (binnedAccounts.isEmpty())
|
||||||
|
@ -71,7 +71,8 @@ public class BlockChain {
|
|||||||
|
|
||||||
public enum FeatureTrigger {
|
public enum FeatureTrigger {
|
||||||
atFindNextTransactionFix,
|
atFindNextTransactionFix,
|
||||||
newBlockSigHeight;
|
newBlockSigHeight,
|
||||||
|
shareBinFix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Map of which blockchain features are enabled when (height/timestamp) */
|
/** Map of which blockchain features are enabled when (height/timestamp) */
|
||||||
@ -381,6 +382,10 @@ public class BlockChain {
|
|||||||
return this.featureTriggers.get(FeatureTrigger.newBlockSigHeight.name()).intValue();
|
return this.featureTriggers.get(FeatureTrigger.newBlockSigHeight.name()).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getShareBinFixHeight() {
|
||||||
|
return this.featureTriggers.get(FeatureTrigger.shareBinFix.name()).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
// More complex getters for aspects that change by height or timestamp
|
// More complex getters for aspects that change by height or timestamp
|
||||||
|
|
||||||
public long getRewardAtHeight(int ourHeight) {
|
public long getRewardAtHeight(int ourHeight) {
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
},
|
},
|
||||||
"featureTriggers": {
|
"featureTriggers": {
|
||||||
"atFindNextTransactionFix": 275000,
|
"atFindNextTransactionFix": 275000,
|
||||||
"newBlockSigHeight": 320000
|
"newBlockSigHeight": 320000,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -46,7 +46,8 @@
|
|||||||
"newAssetPricingTimestamp": 0,
|
"newAssetPricingTimestamp": 0,
|
||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
"newAssetPricingTimestamp": 0,
|
"newAssetPricingTimestamp": 0,
|
||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
"newAssetPricingTimestamp": 0,
|
"newAssetPricingTimestamp": 0,
|
||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
"newAssetPricingTimestamp": 0,
|
"newAssetPricingTimestamp": 0,
|
||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
"newAssetPricingTimestamp": 0,
|
"newAssetPricingTimestamp": 0,
|
||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
74
src/test/resources/test-chain-v2-reward-levels.json
Normal file
74
src/test/resources/test-chain-v2-reward-levels.json
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"isTestChain": true,
|
||||||
|
"blockTimestampMargin": 500,
|
||||||
|
"transactionExpiryPeriod": 86400000,
|
||||||
|
"maxBlockSize": 2097152,
|
||||||
|
"maxBytesPerUnitFee": 1024,
|
||||||
|
"unitFee": "0.1",
|
||||||
|
"requireGroupForApproval": false,
|
||||||
|
"minAccountLevelToRewardShare": 5,
|
||||||
|
"maxRewardSharesPerMintingAccount": 20,
|
||||||
|
"founderEffectiveMintingLevel": 10,
|
||||||
|
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||||
|
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||||
|
"rewardsByHeight": [
|
||||||
|
{ "height": 1, "reward": 100 },
|
||||||
|
{ "height": 11, "reward": 10 },
|
||||||
|
{ "height": 21, "reward": 1 }
|
||||||
|
],
|
||||||
|
"sharesByLevel": [
|
||||||
|
{ "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
|
{ "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
|
{ "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
|
{ "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
|
{ "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShare": 0.20,
|
||||||
|
"qoraPerQortReward": 250,
|
||||||
|
"blocksNeededByLevel": [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ],
|
||||||
|
"blockTimingsByHeight": [
|
||||||
|
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
|
||||||
|
],
|
||||||
|
"ciyamAtSettings": {
|
||||||
|
"feePerStep": "0.0001",
|
||||||
|
"maxStepsPerRound": 500,
|
||||||
|
"stepsPerFunctionCall": 10,
|
||||||
|
"minutesPerBlock": 1
|
||||||
|
},
|
||||||
|
"featureTriggers": {
|
||||||
|
"messageHeight": 0,
|
||||||
|
"atHeight": 0,
|
||||||
|
"assetsTimestamp": 0,
|
||||||
|
"votingTimestamp": 0,
|
||||||
|
"arbitraryTimestamp": 0,
|
||||||
|
"powfixTimestamp": 0,
|
||||||
|
"qortalTimestamp": 0,
|
||||||
|
"newAssetPricingTimestamp": 0,
|
||||||
|
"groupApprovalTimestamp": 0,
|
||||||
|
"atFindNextTransactionFix": 0,
|
||||||
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 6
|
||||||
|
},
|
||||||
|
"genesisInfo": {
|
||||||
|
"version": 4,
|
||||||
|
"timestamp": 0,
|
||||||
|
"transactions": [
|
||||||
|
{ "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
||||||
|
{ "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
|
{ "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
|
|
||||||
|
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
||||||
|
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
||||||
|
{ "type": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000" },
|
||||||
|
{ "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000" },
|
||||||
|
|
||||||
|
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||||
|
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
||||||
|
|
||||||
|
{ "type": "ACCOUNT_LEVEL", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "level": 1 },
|
||||||
|
{ "type": "ACCOUNT_LEVEL", "target": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "level": 1 },
|
||||||
|
{ "type": "ACCOUNT_LEVEL", "target": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "level": 1 },
|
||||||
|
{ "type": "ACCOUNT_LEVEL", "target": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "level": 2 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -46,7 +46,8 @@
|
|||||||
"newAssetPricingTimestamp": 0,
|
"newAssetPricingTimestamp": 0,
|
||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
"newAssetPricingTimestamp": 0,
|
"newAssetPricingTimestamp": 0,
|
||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999
|
"newBlockSigHeight": 999999,
|
||||||
|
"shareBinFix": 999999
|
||||||
},
|
},
|
||||||
"genesisInfo": {
|
"genesisInfo": {
|
||||||
"version": 4,
|
"version": 4,
|
||||||
|
7
src/test/resources/test-settings-v2-reward-levels.json
Normal file
7
src/test/resources/test-settings-v2-reward-levels.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"restrictedApi": false,
|
||||||
|
"blockchainConfig": "src/test/resources/test-chain-v2-reward-levels.json",
|
||||||
|
"wipeUnconfirmedOnStart": false,
|
||||||
|
"testNtpOffset": 0,
|
||||||
|
"minPeers": 0
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user