From f7e2ee383e06e4a180f867e95390116122f6c664 Mon Sep 17 00:00:00 2001 From: catbref Date: Wed, 18 Mar 2020 18:03:56 +0000 Subject: [PATCH] More complete testing of block reward distribution to founders --- .../org/qortal/test/minting/RewardTests.java | 53 ++++++++++++++++ .../test-chain-v2-founder-rewards.json | 63 +++++++++++++++++++ .../test-settings-v2-founder-rewards.json | 6 ++ 3 files changed, 122 insertions(+) create mode 100644 src/test/resources/test-chain-v2-founder-rewards.json create mode 100644 src/test/resources/test-settings-v2-founder-rewards.json diff --git a/src/test/java/org/qortal/test/minting/RewardTests.java b/src/test/java/org/qortal/test/minting/RewardTests.java index c2d3bd17..5b2bfdbf 100644 --- a/src/test/java/org/qortal/test/minting/RewardTests.java +++ b/src/test/java/org/qortal/test/minting/RewardTests.java @@ -4,9 +4,11 @@ import static org.junit.Assert.*; import java.math.BigDecimal; import java.math.RoundingMode; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.bitcoinj.core.Base58; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -204,4 +206,55 @@ public class RewardTests extends Common { } } + /** Test rewards to founders, one in reward-share, the other is self-share. */ + @Test + public void testFounderRewards() throws DataException { + Common.useSettings("test-settings-v2-founder-rewards.json"); + + BigDecimal perHundred = BigDecimal.valueOf(100L); + + try (final Repository repository = RepositoryManager.getRepository()) { + BigDecimal blockReward = BlockUtils.getNextBlockReward(repository); + + List mintingAndOnlineAccounts = new ArrayList<>(); + + // Alice to mint, therefore online + PrivateKeyAccount aliceSelfShare = Common.getTestAccount(repository, "alice-reward-share"); + mintingAndOnlineAccounts.add(aliceSelfShare); + + // Bob self-share NOT online + + // Chloe self-share and reward-share with Dilbert both online + PrivateKeyAccount chloeSelfShare = Common.getTestAccount(repository, "chloe-reward-share"); + mintingAndOnlineAccounts.add(chloeSelfShare); + PrivateKeyAccount chloeDilbertRewardShare = new PrivateKeyAccount(repository, Base58.decode("HuiyqLipUN1V9p1HZfLhyEwmEA6BTaT2qEfjgkwPViV4")); + mintingAndOnlineAccounts.add(chloeDilbertRewardShare); + + BlockMinter.mintTestingBlock(repository, mintingAndOnlineAccounts.toArray(new PrivateKeyAccount[0])); + + // 3 founders (online or not) so blockReward divided by 3 + BigDecimal founderCount = BigDecimal.valueOf(3L); + BigDecimal perFounderReward = blockReward.divide(founderCount, RoundingMode.DOWN); + + // Alice simple self-share so her reward is perFounderReward + AccountUtils.assertBalance(repository, "alice", Asset.QORT, perFounderReward); + + // Bob not online so his reward is simply perFounderReward + AccountUtils.assertBalance(repository, "bob", Asset.QORT, perFounderReward); + + // Chloe has two reward-shares, so her reward is divided by 2 + BigDecimal chloeSharesCount = BigDecimal.valueOf(2L); + BigDecimal chloePerShareReward = perFounderReward.divide(chloeSharesCount, RoundingMode.DOWN); + // Her self-share gets chloePerShareReward + BigDecimal chloeExpectedBalance = chloePerShareReward; + // Her reward-share with Dilbert: 25% goes to Dilbert + BigDecimal dilbertSharePercent = BigDecimal.valueOf(25L); + BigDecimal dilbertExpectedBalance = chloePerShareReward.multiply(dilbertSharePercent).divide(perHundred, RoundingMode.DOWN); + // The remaining 75% goes to Chloe + BigDecimal rewardShareRemaining = chloePerShareReward.subtract(dilbertExpectedBalance); + chloeExpectedBalance = chloeExpectedBalance.add(rewardShareRemaining); + AccountUtils.assertBalance(repository, "chloe", Asset.QORT, chloeExpectedBalance); + } + } + } \ No newline at end of file diff --git a/src/test/resources/test-chain-v2-founder-rewards.json b/src/test/resources/test-chain-v2-founder-rewards.json new file mode 100644 index 00000000..2c315c79 --- /dev/null +++ b/src/test/resources/test-chain-v2-founder-rewards.json @@ -0,0 +1,63 @@ +{ + "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 } + ], + "featureTriggers": { + "messageHeight": 0, + "atHeight": 0, + "assetsTimestamp": 0, + "votingTimestamp": 0, + "arbitraryTimestamp": 0, + "powfixTimestamp": 0, + "qortalTimestamp": 0, + "newAssetPricingTimestamp": 0, + "groupApprovalTimestamp": 0 + }, + "genesisInfo": { + "version": 4, + "timestamp": 0, + "transactions": [ + { "type": "ISSUE_ASSET", "owner": "QcFmNxSArv5tWEzCtTKb2Lqc5QkKuQ7RNs", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0, "reference": "3Verk6ZKBJc3WTTVfxFC9icSjKdM8b92eeJEpJP8qNizG4ZszNFq8wdDYdSjJXq2iogDFR1njyhsBdVpbvDfjzU7" }, + { "type": "ISSUE_ASSET", "owner": "QUwGVHPPxJNJ2dq95abQNe79EyBN2K26zM", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, + { "type": "ISSUE_ASSET", "owner": "QUwGVHPPxJNJ2dq95abQNe79EyBN2K26zM", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, + + { "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 }, + { "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 }, + + { "type": "ACCOUNT_FLAGS", "target": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "andMask": -1, "orMask": 1, "xorMask": 0 }, + { "type": "REWARD_SHARE", "minterPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "rewardSharePublicKey": "CcABzvk26TFEHG7Yok84jxyd4oBtLkx8RJdGFVz2csvp", "sharePercent": 100 }, + + { "type": "ACCOUNT_FLAGS", "target": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "andMask": -1, "orMask": 1, "xorMask": 0 }, + { "type": "REWARD_SHARE", "minterPublicKey": "7KNBj2MnEb6zq1vvKY1q8G2Voctcc2Z1X4avFyEH2eJC", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "rewardSharePublicKey": "6bnEKqZbsCSWryUQnbBT9Umufdu3CapFvxfAni6afhFb", "sharePercent": 100 }, + { "type": "REWARD_SHARE", "minterPublicKey": "7KNBj2MnEb6zq1vvKY1q8G2Voctcc2Z1X4avFyEH2eJC", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "rewardSharePublicKey": "Hebh14YXUdJA66Vq8KyffNXHx3NSDUAZaNH9qbfEvf5M", "sharePercent": 25 } + + ] + } +} diff --git a/src/test/resources/test-settings-v2-founder-rewards.json b/src/test/resources/test-settings-v2-founder-rewards.json new file mode 100644 index 00000000..1751cf7d --- /dev/null +++ b/src/test/resources/test-settings-v2-founder-rewards.json @@ -0,0 +1,6 @@ +{ + "restrictedApi": false, + "blockchainConfig": "src/test/resources/test-chain-v2-founder-rewards.json", + "wipeUnconfirmedOnStart": false, + "minPeers": 0 +}