forked from Qortal/qortal
Merge branch 'shares-by-level-rework'
This commit is contained in:
commit
5807d6e0dc
@ -10,7 +10,6 @@ import java.math.BigInteger;
|
|||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -185,8 +184,11 @@ public class Block {
|
|||||||
if (accountLevel <= 0)
|
if (accountLevel <= 0)
|
||||||
return null; // level 0 isn't included in any share bins
|
return null; // level 0 isn't included in any share bins
|
||||||
|
|
||||||
|
// Select the correct set of share bins based on block height
|
||||||
final BlockChain blockChain = BlockChain.getInstance();
|
final BlockChain blockChain = BlockChain.getInstance();
|
||||||
final AccountLevelShareBin[] shareBinsByLevel = blockChain.getShareBinsByAccountLevel();
|
final AccountLevelShareBin[] shareBinsByLevel = (blockHeight >= blockChain.getSharesByLevelV2Height()) ?
|
||||||
|
blockChain.getShareBinsByAccountLevelV2() : blockChain.getShareBinsByAccountLevelV1();
|
||||||
|
|
||||||
if (accountLevel > shareBinsByLevel.length)
|
if (accountLevel > shareBinsByLevel.length)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -1896,10 +1898,14 @@ public class Block {
|
|||||||
final List<ExpandedAccount> onlineFounderAccounts = expandedAccounts.stream().filter(expandedAccount -> expandedAccount.isMinterFounder).collect(Collectors.toList());
|
final List<ExpandedAccount> onlineFounderAccounts = expandedAccounts.stream().filter(expandedAccount -> expandedAccount.isMinterFounder).collect(Collectors.toList());
|
||||||
final boolean haveFounders = !onlineFounderAccounts.isEmpty();
|
final boolean haveFounders = !onlineFounderAccounts.isEmpty();
|
||||||
|
|
||||||
|
// Select the correct set of share bins based on block height
|
||||||
|
List<AccountLevelShareBin> accountLevelShareBinsForBlock = (this.blockData.getHeight() >= BlockChain.getInstance().getSharesByLevelV2Height()) ?
|
||||||
|
BlockChain.getInstance().getAccountLevelShareBinsV2() : BlockChain.getInstance().getAccountLevelShareBinsV1();
|
||||||
|
|
||||||
// Determine reward candidates based on account level
|
// Determine reward candidates based on account level
|
||||||
// This needs a deep copy, so the shares can be modified when tiers aren't activated yet
|
// This needs a deep copy, so the shares can be modified when tiers aren't activated yet
|
||||||
List<AccountLevelShareBin> accountLevelShareBins = new ArrayList<>();
|
List<AccountLevelShareBin> accountLevelShareBins = new ArrayList<>();
|
||||||
for (AccountLevelShareBin accountLevelShareBin : BlockChain.getInstance().getAccountLevelShareBins()) {
|
for (AccountLevelShareBin accountLevelShareBin : accountLevelShareBinsForBlock) {
|
||||||
accountLevelShareBins.add((AccountLevelShareBin) accountLevelShareBin.clone());
|
accountLevelShareBins.add((AccountLevelShareBin) accountLevelShareBin.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1975,7 +1981,7 @@ public class Block {
|
|||||||
// Fetch list of legacy QORA holders who haven't reached their cap of QORT reward.
|
// Fetch list of legacy QORA holders who haven't reached their cap of QORT reward.
|
||||||
List<EligibleQoraHolderData> qoraHolders = this.repository.getAccountRepository().getEligibleLegacyQoraHolders(isProcessingNotOrphaning ? null : this.blockData.getHeight());
|
List<EligibleQoraHolderData> qoraHolders = this.repository.getAccountRepository().getEligibleLegacyQoraHolders(isProcessingNotOrphaning ? null : this.blockData.getHeight());
|
||||||
final boolean haveQoraHolders = !qoraHolders.isEmpty();
|
final boolean haveQoraHolders = !qoraHolders.isEmpty();
|
||||||
final long qoraHoldersShare = BlockChain.getInstance().getQoraHoldersShare();
|
final long qoraHoldersShare = BlockChain.getInstance().getQoraHoldersShareAtHeight(this.blockData.getHeight());
|
||||||
|
|
||||||
// Perform account-level-based reward scaling if appropriate
|
// Perform account-level-based reward scaling if appropriate
|
||||||
if (!haveFounders) {
|
if (!haveFounders) {
|
||||||
|
@ -68,6 +68,7 @@ public class BlockChain {
|
|||||||
atFindNextTransactionFix,
|
atFindNextTransactionFix,
|
||||||
newBlockSigHeight,
|
newBlockSigHeight,
|
||||||
shareBinFix,
|
shareBinFix,
|
||||||
|
sharesByLevelV2Height,
|
||||||
rewardShareLimitTimestamp,
|
rewardShareLimitTimestamp,
|
||||||
calcChainWeightTimestamp,
|
calcChainWeightTimestamp,
|
||||||
transactionV5Timestamp,
|
transactionV5Timestamp,
|
||||||
@ -122,13 +123,19 @@ public class BlockChain {
|
|||||||
return shareBinCopy;
|
return shareBinCopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private List<AccountLevelShareBin> sharesByLevel;
|
private List<AccountLevelShareBin> sharesByLevelV1;
|
||||||
|
private List<AccountLevelShareBin> sharesByLevelV2;
|
||||||
/** Generated lookup of share-bin by account level */
|
/** Generated lookup of share-bin by account level */
|
||||||
private AccountLevelShareBin[] shareBinsByLevel;
|
private AccountLevelShareBin[] shareBinsByLevelV1;
|
||||||
|
private AccountLevelShareBin[] shareBinsByLevelV2;
|
||||||
|
|
||||||
/** Share of block reward/fees to legacy QORA coin holders */
|
/** Share of block reward/fees to legacy QORA coin holders, by block height */
|
||||||
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
public static class ShareByHeight {
|
||||||
private Long qoraHoldersShare;
|
public int height;
|
||||||
|
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
||||||
|
public long share;
|
||||||
|
}
|
||||||
|
private List<ShareByHeight> qoraHoldersShareByHeight;
|
||||||
|
|
||||||
/** How many legacy QORA per 1 QORT of block reward. */
|
/** How many legacy QORA per 1 QORT of block reward. */
|
||||||
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
||||||
@ -366,12 +373,20 @@ public class BlockChain {
|
|||||||
return this.rewardsByHeight;
|
return this.rewardsByHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AccountLevelShareBin> getAccountLevelShareBins() {
|
public List<AccountLevelShareBin> getAccountLevelShareBinsV1() {
|
||||||
return this.sharesByLevel;
|
return this.sharesByLevelV1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountLevelShareBin[] getShareBinsByAccountLevel() {
|
public List<AccountLevelShareBin> getAccountLevelShareBinsV2() {
|
||||||
return this.shareBinsByLevel;
|
return this.sharesByLevelV2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountLevelShareBin[] getShareBinsByAccountLevelV1() {
|
||||||
|
return this.shareBinsByLevelV1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountLevelShareBin[] getShareBinsByAccountLevelV2() {
|
||||||
|
return this.shareBinsByLevelV2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Integer> getBlocksNeededByLevel() {
|
public List<Integer> getBlocksNeededByLevel() {
|
||||||
@ -382,10 +397,6 @@ public class BlockChain {
|
|||||||
return this.cumulativeBlocksByLevel;
|
return this.cumulativeBlocksByLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getQoraHoldersShare() {
|
|
||||||
return this.qoraHoldersShare;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getQoraPerQortReward() {
|
public long getQoraPerQortReward() {
|
||||||
return this.qoraPerQortReward;
|
return this.qoraPerQortReward;
|
||||||
}
|
}
|
||||||
@ -444,6 +455,10 @@ public class BlockChain {
|
|||||||
return this.featureTriggers.get(FeatureTrigger.shareBinFix.name()).intValue();
|
return this.featureTriggers.get(FeatureTrigger.shareBinFix.name()).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSharesByLevelV2Height() {
|
||||||
|
return this.featureTriggers.get(FeatureTrigger.sharesByLevelV2Height.name()).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
public long getRewardShareLimitTimestamp() {
|
public long getRewardShareLimitTimestamp() {
|
||||||
return this.featureTriggers.get(FeatureTrigger.rewardShareLimitTimestamp.name()).longValue();
|
return this.featureTriggers.get(FeatureTrigger.rewardShareLimitTimestamp.name()).longValue();
|
||||||
}
|
}
|
||||||
@ -504,6 +519,15 @@ public class BlockChain {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getQoraHoldersShareAtHeight(int ourHeight) {
|
||||||
|
// Scan through for QORA share at our height
|
||||||
|
for (int i = qoraHoldersShareByHeight.size() - 1; i >= 0; --i)
|
||||||
|
if (qoraHoldersShareByHeight.get(i).height <= ourHeight)
|
||||||
|
return qoraHoldersShareByHeight.get(i).share;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Validate blockchain config read from JSON */
|
/** Validate blockchain config read from JSON */
|
||||||
private void validateConfig() {
|
private void validateConfig() {
|
||||||
if (this.genesisInfo == null)
|
if (this.genesisInfo == null)
|
||||||
@ -512,11 +536,14 @@ public class BlockChain {
|
|||||||
if (this.rewardsByHeight == null)
|
if (this.rewardsByHeight == null)
|
||||||
Settings.throwValidationError("No \"rewardsByHeight\" entry found in blockchain config");
|
Settings.throwValidationError("No \"rewardsByHeight\" entry found in blockchain config");
|
||||||
|
|
||||||
if (this.sharesByLevel == null)
|
if (this.sharesByLevelV1 == null)
|
||||||
Settings.throwValidationError("No \"sharesByLevel\" entry found in blockchain config");
|
Settings.throwValidationError("No \"sharesByLevelV1\" entry found in blockchain config");
|
||||||
|
|
||||||
if (this.qoraHoldersShare == null)
|
if (this.sharesByLevelV2 == null)
|
||||||
Settings.throwValidationError("No \"qoraHoldersShare\" entry found in blockchain config");
|
Settings.throwValidationError("No \"sharesByLevelV2\" entry found in blockchain config");
|
||||||
|
|
||||||
|
if (this.qoraHoldersShareByHeight == null)
|
||||||
|
Settings.throwValidationError("No \"qoraHoldersShareByHeight\" entry found in blockchain config");
|
||||||
|
|
||||||
if (this.qoraPerQortReward == null)
|
if (this.qoraPerQortReward == null)
|
||||||
Settings.throwValidationError("No \"qoraPerQortReward\" entry found in blockchain config");
|
Settings.throwValidationError("No \"qoraPerQortReward\" entry found in blockchain config");
|
||||||
@ -553,13 +580,22 @@ public class BlockChain {
|
|||||||
if (!this.featureTriggers.containsKey(featureTrigger.name()))
|
if (!this.featureTriggers.containsKey(featureTrigger.name()))
|
||||||
Settings.throwValidationError(String.format("Missing feature trigger \"%s\" in blockchain config", featureTrigger.name()));
|
Settings.throwValidationError(String.format("Missing feature trigger \"%s\" in blockchain config", featureTrigger.name()));
|
||||||
|
|
||||||
// Check block reward share bounds
|
// Check block reward share bounds (V1)
|
||||||
long totalShare = this.qoraHoldersShare;
|
long totalShareV1 = this.qoraHoldersShareByHeight.get(0).share;
|
||||||
// Add share percents for account-level-based rewards
|
// Add share percents for account-level-based rewards
|
||||||
for (AccountLevelShareBin accountLevelShareBin : this.sharesByLevel)
|
for (AccountLevelShareBin accountLevelShareBin : this.sharesByLevelV1)
|
||||||
totalShare += accountLevelShareBin.share;
|
totalShareV1 += accountLevelShareBin.share;
|
||||||
|
|
||||||
if (totalShare < 0 || totalShare > 1_00000000L)
|
if (totalShareV1 < 0 || totalShareV1 > 1_00000000L)
|
||||||
|
Settings.throwValidationError("Total non-founder share out of bounds (0<x<1e8)");
|
||||||
|
|
||||||
|
// Check block reward share bounds (V2)
|
||||||
|
long totalShareV2 = this.qoraHoldersShareByHeight.get(1).share;
|
||||||
|
// Add share percents for account-level-based rewards
|
||||||
|
for (AccountLevelShareBin accountLevelShareBin : this.sharesByLevelV2)
|
||||||
|
totalShareV2 += accountLevelShareBin.share;
|
||||||
|
|
||||||
|
if (totalShareV2 < 0 || totalShareV2 > 1_00000000L)
|
||||||
Settings.throwValidationError("Total non-founder share out of bounds (0<x<1e8)");
|
Settings.throwValidationError("Total non-founder share out of bounds (0<x<1e8)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,23 +611,34 @@ public class BlockChain {
|
|||||||
cumulativeBlocks += this.blocksNeededByLevel.get(level);
|
cumulativeBlocks += this.blocksNeededByLevel.get(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate lookup-array for account-level share bins
|
// Generate lookup-array for account-level share bins (V1)
|
||||||
AccountLevelShareBin lastAccountLevelShareBin = this.sharesByLevel.get(this.sharesByLevel.size() - 1);
|
AccountLevelShareBin lastAccountLevelShareBinV1 = this.sharesByLevelV1.get(this.sharesByLevelV1.size() - 1);
|
||||||
final int lastLevel = lastAccountLevelShareBin.levels.get(lastAccountLevelShareBin.levels.size() - 1);
|
final int lastLevelV1 = lastAccountLevelShareBinV1.levels.get(lastAccountLevelShareBinV1.levels.size() - 1);
|
||||||
this.shareBinsByLevel = new AccountLevelShareBin[lastLevel];
|
this.shareBinsByLevelV1 = new AccountLevelShareBin[lastLevelV1];
|
||||||
|
for (AccountLevelShareBin accountLevelShareBin : this.sharesByLevelV1)
|
||||||
for (AccountLevelShareBin accountLevelShareBin : this.sharesByLevel)
|
|
||||||
for (int level : accountLevelShareBin.levels)
|
for (int level : accountLevelShareBin.levels)
|
||||||
// level 1 stored at index 0, level 2 stored at index 1, etc.
|
// level 1 stored at index 0, level 2 stored at index 1, etc.
|
||||||
// level 0 not allowed
|
// level 0 not allowed
|
||||||
this.shareBinsByLevel[level - 1] = accountLevelShareBin;
|
this.shareBinsByLevelV1[level - 1] = accountLevelShareBin;
|
||||||
|
|
||||||
|
// Generate lookup-array for account-level share bins (V2)
|
||||||
|
AccountLevelShareBin lastAccountLevelShareBinV2 = this.sharesByLevelV2.get(this.sharesByLevelV2.size() - 1);
|
||||||
|
final int lastLevelV2 = lastAccountLevelShareBinV2.levels.get(lastAccountLevelShareBinV2.levels.size() - 1);
|
||||||
|
this.shareBinsByLevelV2 = new AccountLevelShareBin[lastLevelV2];
|
||||||
|
for (AccountLevelShareBin accountLevelShareBin : this.sharesByLevelV2)
|
||||||
|
for (int level : accountLevelShareBin.levels)
|
||||||
|
// level 1 stored at index 0, level 2 stored at index 1, etc.
|
||||||
|
// level 0 not allowed
|
||||||
|
this.shareBinsByLevelV2[level - 1] = accountLevelShareBin;
|
||||||
|
|
||||||
// Convert collections to unmodifiable form
|
// Convert collections to unmodifiable form
|
||||||
this.rewardsByHeight = Collections.unmodifiableList(this.rewardsByHeight);
|
this.rewardsByHeight = Collections.unmodifiableList(this.rewardsByHeight);
|
||||||
this.sharesByLevel = Collections.unmodifiableList(this.sharesByLevel);
|
this.sharesByLevelV1 = Collections.unmodifiableList(this.sharesByLevelV1);
|
||||||
|
this.sharesByLevelV2 = Collections.unmodifiableList(this.sharesByLevelV2);
|
||||||
this.blocksNeededByLevel = Collections.unmodifiableList(this.blocksNeededByLevel);
|
this.blocksNeededByLevel = Collections.unmodifiableList(this.blocksNeededByLevel);
|
||||||
this.cumulativeBlocksByLevel = Collections.unmodifiableList(this.cumulativeBlocksByLevel);
|
this.cumulativeBlocksByLevel = Collections.unmodifiableList(this.cumulativeBlocksByLevel);
|
||||||
this.blockTimingsByHeight = Collections.unmodifiableList(this.blockTimingsByHeight);
|
this.blockTimingsByHeight = Collections.unmodifiableList(this.blockTimingsByHeight);
|
||||||
|
this.qoraHoldersShareByHeight = Collections.unmodifiableList(this.qoraHoldersShareByHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,14 +39,24 @@
|
|||||||
{ "height": 2851201, "reward": 2.25 },
|
{ "height": 2851201, "reward": 2.25 },
|
||||||
{ "height": 3110401, "reward": 2.00 }
|
{ "height": 3110401, "reward": 2.00 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 9999999, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -64,6 +74,7 @@
|
|||||||
"atFindNextTransactionFix": 275000,
|
"atFindNextTransactionFix": 275000,
|
||||||
"newBlockSigHeight": 320000,
|
"newBlockSigHeight": 320000,
|
||||||
"shareBinFix": 399000,
|
"shareBinFix": 399000,
|
||||||
|
"sharesByLevelV2Height": 9999999,
|
||||||
"rewardShareLimitTimestamp": 1657382400000,
|
"rewardShareLimitTimestamp": 1657382400000,
|
||||||
"calcChainWeightTimestamp": 1620579600000,
|
"calcChainWeightTimestamp": 1620579600000,
|
||||||
"transactionV5Timestamp": 1642176000000,
|
"transactionV5Timestamp": 1642176000000,
|
||||||
|
@ -13,6 +13,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.qortal.account.PrivateKeyAccount;
|
import org.qortal.account.PrivateKeyAccount;
|
||||||
import org.qortal.asset.Asset;
|
import org.qortal.asset.Asset;
|
||||||
|
import org.qortal.block.Block;
|
||||||
import org.qortal.block.BlockChain;
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.block.BlockChain.RewardByHeight;
|
import org.qortal.block.BlockChain.RewardByHeight;
|
||||||
import org.qortal.controller.BlockMinter;
|
import org.qortal.controller.BlockMinter;
|
||||||
@ -108,7 +109,7 @@ public class RewardTests extends Common {
|
|||||||
public void testLegacyQoraReward() throws DataException {
|
public void testLegacyQoraReward() throws DataException {
|
||||||
Common.useSettings("test-settings-v2-qora-holder-extremes.json");
|
Common.useSettings("test-settings-v2-qora-holder-extremes.json");
|
||||||
|
|
||||||
long qoraHoldersShare = BlockChain.getInstance().getQoraHoldersShare();
|
long qoraHoldersShare = BlockChain.getInstance().getQoraHoldersShareAtHeight(1);
|
||||||
BigInteger qoraHoldersShareBI = BigInteger.valueOf(qoraHoldersShare);
|
BigInteger qoraHoldersShareBI = BigInteger.valueOf(qoraHoldersShare);
|
||||||
|
|
||||||
long qoraPerQort = BlockChain.getInstance().getQoraPerQortReward();
|
long qoraPerQort = BlockChain.getInstance().getQoraPerQortReward();
|
||||||
@ -189,6 +190,47 @@ public class RewardTests extends Common {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLegacyQoraRewardReduction() throws DataException {
|
||||||
|
Common.useSettings("test-settings-v2-qora-holder-reduction.json");
|
||||||
|
|
||||||
|
// Make sure that the QORA share reduces between blocks 4 and 5
|
||||||
|
assertTrue(BlockChain.getInstance().getQoraHoldersShareAtHeight(5) < BlockChain.getInstance().getQoraHoldersShareAtHeight(4));
|
||||||
|
|
||||||
|
// Keep track of balance deltas at each height
|
||||||
|
Map<Integer, Long> chloeQortBalanceDeltaAtEachHeight = new HashMap<>();
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
Map<String, Map<Long, Long>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT, Asset.LEGACY_QORA, Asset.QORT_FROM_QORA);
|
||||||
|
long chloeLastQortBalance = initialBalances.get("chloe").get(Asset.QORT);
|
||||||
|
|
||||||
|
for (int i=2; i<=10; i++) {
|
||||||
|
|
||||||
|
Block block = BlockUtils.mintBlock(repository);
|
||||||
|
|
||||||
|
// Add to map of balance deltas at each height
|
||||||
|
long chloeNewQortBalance = AccountUtils.getBalance(repository, "chloe", Asset.QORT);
|
||||||
|
chloeQortBalanceDeltaAtEachHeight.put(block.getBlockData().getHeight(), chloeNewQortBalance - chloeLastQortBalance);
|
||||||
|
chloeLastQortBalance = chloeNewQortBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure blocks 2-4 paid out the same rewards to Chloe
|
||||||
|
assertEquals(chloeQortBalanceDeltaAtEachHeight.get(2), chloeQortBalanceDeltaAtEachHeight.get(4));
|
||||||
|
|
||||||
|
// Ensure block 5 paid a lower reward
|
||||||
|
assertTrue(chloeQortBalanceDeltaAtEachHeight.get(5) < chloeQortBalanceDeltaAtEachHeight.get(4));
|
||||||
|
|
||||||
|
// Check that the reward was 20x lower
|
||||||
|
assertTrue(chloeQortBalanceDeltaAtEachHeight.get(5) == chloeQortBalanceDeltaAtEachHeight.get(4) / 20);
|
||||||
|
|
||||||
|
// Orphan to block 4 and ensure that Chloe's balance hasn't been incorrectly affected by the reward reduction
|
||||||
|
BlockUtils.orphanToBlock(repository, 4);
|
||||||
|
long expectedChloeQortBalance = initialBalances.get("chloe").get(Asset.QORT) + chloeQortBalanceDeltaAtEachHeight.get(2) +
|
||||||
|
chloeQortBalanceDeltaAtEachHeight.get(3) + chloeQortBalanceDeltaAtEachHeight.get(4);
|
||||||
|
assertEquals(expectedChloeQortBalance, AccountUtils.getBalance(repository, "chloe", Asset.QORT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Use Alice-Chloe reward-share to bump Chloe from level 0 to level 1, then check orphaning works as expected. */
|
/** Use Alice-Chloe reward-share to bump Chloe from level 0 to level 1, then check orphaning works as expected. */
|
||||||
@Test
|
@Test
|
||||||
public void testLevel1() throws DataException {
|
public void testLevel1() throws DataException {
|
||||||
@ -294,7 +336,7 @@ public class RewardTests extends Common {
|
|||||||
* So Dilbert should receive 100% - legacy QORA holder's share.
|
* So Dilbert should receive 100% - legacy QORA holder's share.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final long qoraHoldersShare = BlockChain.getInstance().getQoraHoldersShare();
|
final long qoraHoldersShare = BlockChain.getInstance().getQoraHoldersShareAtHeight(1);
|
||||||
final long remainingShare = 1_00000000 - qoraHoldersShare;
|
final long remainingShare = 1_00000000 - qoraHoldersShare;
|
||||||
|
|
||||||
long dilbertExpectedBalance = initialBalances.get("dilbert").get(Asset.QORT);
|
long dilbertExpectedBalance = initialBalances.get("dilbert").get(Asset.QORT);
|
||||||
@ -1140,6 +1182,250 @@ public class RewardTests extends Common {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Test rewards for level 1 and 2 accounts with V2 share-bin layout (post QORA reduction) */
|
||||||
|
@Test
|
||||||
|
public void testLevel1And2RewardsShareBinsV2() 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);
|
||||||
|
byte[] chloeRewardSharePrivateKey;
|
||||||
|
// Bob self-share NOT online
|
||||||
|
|
||||||
|
// Mint some blocks, to get us close to the V2 activation, but with some room for Chloe and Dilbert to start minting some blocks
|
||||||
|
for (int i=0; i<990; i++)
|
||||||
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
||||||
|
|
||||||
|
// Chloe self share comes online
|
||||||
|
try {
|
||||||
|
chloeRewardSharePrivateKey = AccountUtils.rewardShare(repository, "chloe", "chloe", 0);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
LOGGER.error("FAILED {}", ex.getLocalizedMessage(), ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
PrivateKeyAccount chloeRewardShareAccount = new PrivateKeyAccount(repository, chloeRewardSharePrivateKey);
|
||||||
|
mintingAndOnlineAccounts.add(chloeRewardShareAccount);
|
||||||
|
|
||||||
|
// Dilbert self share comes online
|
||||||
|
byte[] dilbertRewardSharePrivateKey = AccountUtils.rewardShare(repository, "dilbert", "dilbert", 0);
|
||||||
|
PrivateKeyAccount dilbertRewardShareAccount = new PrivateKeyAccount(repository, dilbertRewardSharePrivateKey);
|
||||||
|
mintingAndOnlineAccounts.add(dilbertRewardShareAccount);
|
||||||
|
|
||||||
|
// Mint 6 more blocks, so that V2 share bins are nearly activated
|
||||||
|
for (int i=0; i<6; i++)
|
||||||
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
||||||
|
|
||||||
|
// Ensure that the levels are as we expect
|
||||||
|
assertEquals(10, (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(1000, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
assertEquals(100000000L, blockReward);
|
||||||
|
|
||||||
|
// We are past the sharesByLevelV2Height feature trigger, so we expect level 1 and 2 to share the increased reward (6%)
|
||||||
|
final int level1And2SharePercent = 6_00; // 6%
|
||||||
|
final long level1And2ShareAmount = (blockReward * level1And2SharePercent) / 100L / 100L;
|
||||||
|
final long expectedLevel1And2RewardV2 = level1And2ShareAmount / 2; // The reward is split between Chloe and Dilbert
|
||||||
|
final long expectedFounderRewardV2 = blockReward - level1And2ShareAmount; // Alice should receive the remainder
|
||||||
|
|
||||||
|
// Validate the balances
|
||||||
|
assertEquals(6000000, level1And2ShareAmount);
|
||||||
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance+expectedFounderRewardV2);
|
||||||
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
||||||
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance+expectedLevel1And2RewardV2);
|
||||||
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance+expectedLevel1And2RewardV2);
|
||||||
|
|
||||||
|
// Now orphan the latest block. This brings us to the threshold of the sharesByLevelV2Height feature trigger
|
||||||
|
BlockUtils.orphanBlocks(repository, 1);
|
||||||
|
assertEquals(999, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
|
||||||
|
// Ensure the latest 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 sharesByLevelV2Height feature trigger.
|
||||||
|
BlockUtils.orphanBlocks(repository, 1);
|
||||||
|
assertEquals(998, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
|
||||||
|
// In V1 of share-bins, level 1-2 pays out 5% instead of 6%
|
||||||
|
final int level1And2SharePercentV1 = 5_00; // 5%
|
||||||
|
final long level1And2ShareAmountV1 = (blockReward * level1And2SharePercentV1) / 100L / 100L;
|
||||||
|
final long expectedLevel1And2RewardV1 = level1And2ShareAmountV1 / 2; // The reward is split between Chloe and Dilbert
|
||||||
|
final long expectedFounderRewardV1 = blockReward - level1And2ShareAmountV1; // Alice should receive the remainder
|
||||||
|
|
||||||
|
// Validate the share amounts and balances
|
||||||
|
assertEquals(5000000, level1And2ShareAmountV1);
|
||||||
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance-expectedFounderRewardV1);
|
||||||
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
||||||
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance-expectedLevel1And2RewardV1);
|
||||||
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance-expectedLevel1And2RewardV1);
|
||||||
|
|
||||||
|
// Orphan the latest block one last time
|
||||||
|
BlockUtils.orphanBlocks(repository, 1);
|
||||||
|
assertEquals(997, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
|
||||||
|
// Validate balances
|
||||||
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance-(expectedFounderRewardV1*2));
|
||||||
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
||||||
|
AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeInitialBalance-(expectedLevel1And2RewardV1*2));
|
||||||
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance-(expectedLevel1And2RewardV1*2));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Test rewards for level 1 and 2 accounts with V2 share-bin layout (post QORA reduction)
|
||||||
|
* plus some legacy QORA holders */
|
||||||
|
@Test
|
||||||
|
public void testLevel1And2RewardsShareBinsV2WithQoraHolders() throws DataException {
|
||||||
|
Common.useSettings("test-settings-v2-qora-holder-extremes.json");
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
|
||||||
|
List<PrivateKeyAccount> mintingAndOnlineAccounts = new ArrayList<>();
|
||||||
|
|
||||||
|
// Some legacy QORA holders exist (Bob and Chloe)
|
||||||
|
|
||||||
|
// Alice self share online
|
||||||
|
PrivateKeyAccount aliceSelfShare = Common.getTestAccount(repository, "alice-reward-share");
|
||||||
|
mintingAndOnlineAccounts.add(aliceSelfShare);
|
||||||
|
byte[] chloeRewardSharePrivateKey;
|
||||||
|
// Bob self-share NOT online
|
||||||
|
|
||||||
|
// Mint some blocks, to get us close to the V2 activation, but with some room for Chloe and Dilbert to start minting some blocks
|
||||||
|
for (int i=0; i<990; i++)
|
||||||
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
||||||
|
|
||||||
|
// Chloe self share comes online
|
||||||
|
try {
|
||||||
|
chloeRewardSharePrivateKey = AccountUtils.rewardShare(repository, "chloe", "chloe", 0);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
LOGGER.error("FAILED {}", ex.getLocalizedMessage(), ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
PrivateKeyAccount chloeRewardShareAccount = new PrivateKeyAccount(repository, chloeRewardSharePrivateKey);
|
||||||
|
mintingAndOnlineAccounts.add(chloeRewardShareAccount);
|
||||||
|
|
||||||
|
// Dilbert self share comes online
|
||||||
|
byte[] dilbertRewardSharePrivateKey = AccountUtils.rewardShare(repository, "dilbert", "dilbert", 0);
|
||||||
|
PrivateKeyAccount dilbertRewardShareAccount = new PrivateKeyAccount(repository, dilbertRewardSharePrivateKey);
|
||||||
|
mintingAndOnlineAccounts.add(dilbertRewardShareAccount);
|
||||||
|
|
||||||
|
// Mint 6 more blocks, so that V2 share bins are nearly activated
|
||||||
|
for (int i=0; i<6; i++)
|
||||||
|
BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0]));
|
||||||
|
|
||||||
|
// Ensure that the levels are as we expect
|
||||||
|
assertEquals(10, (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(1000, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
assertEquals(100000000L, blockReward);
|
||||||
|
|
||||||
|
// We are past the sharesByLevelV2Height feature trigger, so we expect level 1 and 2 to share the increased reward (6%)
|
||||||
|
// and the QORA share will be 1%
|
||||||
|
final int level1And2SharePercent = 6_00; // 6%
|
||||||
|
final int qoraSharePercentV2 = 1_00; // 1%
|
||||||
|
final long qoraShareAmountV2 = (blockReward * qoraSharePercentV2) / 100L / 100L;
|
||||||
|
final long level1And2ShareAmount = (blockReward * level1And2SharePercent) / 100L / 100L;
|
||||||
|
final long expectedLevel1And2RewardV2 = level1And2ShareAmount / 2; // The reward is split between Chloe and Dilbert
|
||||||
|
final long expectedFounderRewardV2 = blockReward - level1And2ShareAmount - qoraShareAmountV2; // Alice should receive the remainder
|
||||||
|
|
||||||
|
// Validate the balances
|
||||||
|
assertEquals(6000000, level1And2ShareAmount);
|
||||||
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance+expectedFounderRewardV2);
|
||||||
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
||||||
|
// Chloe is a QORA holder and will receive additional QORT, so it's not easy to pre-calculate her balance
|
||||||
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance+expectedLevel1And2RewardV2);
|
||||||
|
|
||||||
|
// Now orphan the latest block. This brings us to the threshold of the sharesByLevelV2Height feature trigger
|
||||||
|
BlockUtils.orphanBlocks(repository, 1);
|
||||||
|
assertEquals(999, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
|
||||||
|
// Ensure the latest 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 sharesByLevelV2Height feature trigger.
|
||||||
|
BlockUtils.orphanBlocks(repository, 1);
|
||||||
|
assertEquals(998, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
|
||||||
|
// In V1 of share-bins, level 1-2 pays out 5% instead of 6%, and the QORA share is higher at 20%
|
||||||
|
final int level1And2SharePercentV1 = 5_00; // 5%
|
||||||
|
final int qoraSharePercentV1 = 20_00; // 20%
|
||||||
|
final long qoraShareAmountV1 = (blockReward * qoraSharePercentV1) / 100L / 100L;
|
||||||
|
final long level1And2ShareAmountV1 = (blockReward * level1And2SharePercentV1) / 100L / 100L;
|
||||||
|
final long expectedLevel1And2RewardV1 = level1And2ShareAmountV1 / 2; // The reward is split between Chloe and Dilbert
|
||||||
|
final long expectedFounderRewardV1 = blockReward - level1And2ShareAmountV1 - qoraShareAmountV1; // Alice should receive the remainder
|
||||||
|
|
||||||
|
// Validate the share amounts and balances
|
||||||
|
assertEquals(5000000, level1And2ShareAmountV1);
|
||||||
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance-expectedFounderRewardV1);
|
||||||
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
||||||
|
// Chloe is a QORA holder and will receive additional QORT, so it's not easy to pre-calculate her balance
|
||||||
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance-expectedLevel1And2RewardV1);
|
||||||
|
|
||||||
|
// Orphan the latest block one last time
|
||||||
|
BlockUtils.orphanBlocks(repository, 1);
|
||||||
|
assertEquals(997, (int) repository.getBlockRepository().getLastBlock().getHeight());
|
||||||
|
|
||||||
|
// Validate balances
|
||||||
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, aliceInitialBalance-(expectedFounderRewardV1*2));
|
||||||
|
AccountUtils.assertBalance(repository, "bob", Asset.QORT, bobInitialBalance); // Bob not online so his balance remains the same
|
||||||
|
// Chloe is a QORA holder and will receive additional QORT, so it's not easy to pre-calculate her balance
|
||||||
|
AccountUtils.assertBalance(repository, "dilbert", Asset.QORT, dilbertInitialBalance-(expectedLevel1And2RewardV1*2));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private int getFlags(Repository repository, String name) throws DataException {
|
private int getFlags(Repository repository, String name) throws DataException {
|
||||||
TestAccount testAccount = Common.getTestAccount(repository, name);
|
TestAccount testAccount = Common.getTestAccount(repository, name);
|
||||||
|
@ -19,14 +19,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -54,6 +64,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -23,14 +23,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -57,6 +67,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -58,6 +68,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -58,6 +68,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -58,6 +68,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -20,12 +20,19 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
|
],
|
||||||
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"qoraHoldersShare": 0.20,
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
@ -52,6 +59,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -57,7 +67,8 @@
|
|||||||
"groupApprovalTimestamp": 0,
|
"groupApprovalTimestamp": 0,
|
||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 0,
|
||||||
|
"sharesByLevelV2Height": 1000,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
@ -90,7 +101,10 @@
|
|||||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||||
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
||||||
|
|
||||||
{ "type": "ACCOUNT_LEVEL", "target": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "level": 8 }
|
{ "type": "ACCOUNT_LEVEL", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "level": 1 },
|
||||||
|
{ "type": "ACCOUNT_LEVEL", "target": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "level": 2 },
|
||||||
|
{ "type": "ACCOUNT_LEVEL", "target": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "level": 1 },
|
||||||
|
{ "type": "ACCOUNT_LEVEL", "target": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "level": 1 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
107
src/test/resources/test-chain-v2-qora-holder-reduction.json
Normal file
107
src/test/resources/test-chain-v2-qora-holder-reduction.json
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
"isTestChain": true,
|
||||||
|
"blockTimestampMargin": 500,
|
||||||
|
"transactionExpiryPeriod": 86400000,
|
||||||
|
"maxBlockSize": 2097152,
|
||||||
|
"maxBytesPerUnitFee": 1024,
|
||||||
|
"unitFee": "0.1",
|
||||||
|
"nameRegistrationUnitFees": [
|
||||||
|
{ "timestamp": 1645372800000, "fee": "5" }
|
||||||
|
],
|
||||||
|
"requireGroupForApproval": false,
|
||||||
|
"minAccountLevelToRewardShare": 5,
|
||||||
|
"maxRewardSharesPerFounderMintingAccount": 6,
|
||||||
|
"maxRewardSharesByTimestamp": [
|
||||||
|
{ "timestamp": 0, "maxShares": 6 },
|
||||||
|
{ "timestamp": 9999999999999, "maxShares": 3 }
|
||||||
|
],
|
||||||
|
"founderEffectiveMintingLevel": 10,
|
||||||
|
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||||
|
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||||
|
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||||
|
"rewardsByHeight": [
|
||||||
|
{ "height": 1, "reward": 100 },
|
||||||
|
{ "height": 11, "reward": 10 },
|
||||||
|
{ "height": 21, "reward": 1 }
|
||||||
|
],
|
||||||
|
"sharesByLevelV1": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
|
],
|
||||||
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 5, "share": 0.01 }
|
||||||
|
],
|
||||||
|
"qoraPerQortReward": 250,
|
||||||
|
"minAccountsToActivateShareBin": 30,
|
||||||
|
"shareBinActivationMinLevel": 7,
|
||||||
|
"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": 999999,
|
||||||
|
"sharesByLevelV2Height": 5,
|
||||||
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
|
"calcChainWeightTimestamp": 0,
|
||||||
|
"transactionV5Timestamp": 0,
|
||||||
|
"transactionV6Timestamp": 0,
|
||||||
|
"disableReferenceTimestamp": 9999999999999,
|
||||||
|
"aggregateSignatureTimestamp": 0
|
||||||
|
},
|
||||||
|
"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": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "637557960.49687541", "assetId": 1 },
|
||||||
|
{ "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "0.666", "assetId": 1 },
|
||||||
|
|
||||||
|
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
||||||
|
|
||||||
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
|
|
||||||
|
{ "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": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "level": 8 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -58,6 +68,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 1000,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 1,
|
"minAccountsToActivateShareBin": 1,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -58,6 +68,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 6,
|
"shareBinFix": 6,
|
||||||
|
"sharesByLevelV2Height": 1000,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -58,6 +68,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -23,14 +23,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -57,6 +67,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 0,
|
"rewardShareLimitTimestamp": 0,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"newConsensusTimestamp": 0,
|
"newConsensusTimestamp": 0,
|
||||||
|
@ -24,14 +24,24 @@
|
|||||||
{ "height": 11, "reward": 10 },
|
{ "height": 11, "reward": 10 },
|
||||||
{ "height": 21, "reward": 1 }
|
{ "height": 21, "reward": 1 }
|
||||||
],
|
],
|
||||||
"sharesByLevel": [
|
"sharesByLevelV1": [
|
||||||
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.05 },
|
||||||
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.10 },
|
||||||
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.15 },
|
||||||
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.20 },
|
||||||
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.25 }
|
||||||
],
|
],
|
||||||
"qoraHoldersShare": 0.20,
|
"sharesByLevelV2": [
|
||||||
|
{ "id": 1, "levels": [ 1, 2 ], "share": 0.06 },
|
||||||
|
{ "id": 2, "levels": [ 3, 4 ], "share": 0.13 },
|
||||||
|
{ "id": 3, "levels": [ 5, 6 ], "share": 0.19 },
|
||||||
|
{ "id": 4, "levels": [ 7, 8 ], "share": 0.26 },
|
||||||
|
{ "id": 5, "levels": [ 9, 10 ], "share": 0.32 }
|
||||||
|
],
|
||||||
|
"qoraHoldersShareByHeight": [
|
||||||
|
{ "height": 1, "share": 0.20 },
|
||||||
|
{ "height": 1000000, "share": 0.01 }
|
||||||
|
],
|
||||||
"qoraPerQortReward": 250,
|
"qoraPerQortReward": 250,
|
||||||
"minAccountsToActivateShareBin": 30,
|
"minAccountsToActivateShareBin": 30,
|
||||||
"shareBinActivationMinLevel": 7,
|
"shareBinActivationMinLevel": 7,
|
||||||
@ -58,6 +68,7 @@
|
|||||||
"atFindNextTransactionFix": 0,
|
"atFindNextTransactionFix": 0,
|
||||||
"newBlockSigHeight": 999999,
|
"newBlockSigHeight": 999999,
|
||||||
"shareBinFix": 999999,
|
"shareBinFix": 999999,
|
||||||
|
"sharesByLevelV2Height": 999999,
|
||||||
"rewardShareLimitTimestamp": 9999999999999,
|
"rewardShareLimitTimestamp": 9999999999999,
|
||||||
"calcChainWeightTimestamp": 0,
|
"calcChainWeightTimestamp": 0,
|
||||||
"transactionV5Timestamp": 0,
|
"transactionV5Timestamp": 0,
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"repositoryPath": "testdb",
|
||||||
|
"restrictedApi": false,
|
||||||
|
"blockchainConfig": "src/test/resources/test-chain-v2-qora-holder-reduction.json",
|
||||||
|
"exportPath": "qortal-backup-test",
|
||||||
|
"bootstrap": false,
|
||||||
|
"wipeUnconfirmedOnStart": false,
|
||||||
|
"testNtpOffset": 0,
|
||||||
|
"minPeers": 0,
|
||||||
|
"pruneBlockLimit": 100
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user