]>
Commit | Line | Data |
---|---|---|
db0f9315 S |
1 | #include <gtest/gtest.h> |
2 | ||
3 | #include "main.h" | |
4 | #include "utilmoneystr.h" | |
5 | #include "chainparams.h" | |
6 | #include "utilstrencodings.h" | |
7 | #include "zcash/Address.hpp" | |
8 | #include "wallet/wallet.h" | |
9 | #include "amount.h" | |
10 | #include <memory> | |
11 | #include <string> | |
12 | #include <set> | |
13 | #include <vector> | |
14 | #include <boost/filesystem.hpp> | |
15 | ||
16 | // To run tests: | |
17 | // ./zcash-gtest --gtest_filter="founders_reward_test.*" | |
18 | ||
19 | // | |
20 | // Enable this test to generate and print 48 testnet 2-of-3 multisig addresses. | |
21 | // The output can be copied into chainparams.cpp. | |
88fd8101 | 22 | // The temporary wallet file can be renamed as wallet.dat and used for testing with zcashd. |
db0f9315 S |
23 | // |
24 | #if 0 | |
25 | TEST(founders_reward_test, create_testnet_2of3multisig) { | |
26 | ECC_Start(); | |
27 | SelectParams(CBaseChainParams::TESTNET); | |
28 | boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); | |
88fd8101 | 29 | const std::string path = temp.native() + "-wallet.dat"; |
db0f9315 S |
30 | bool fFirstRun; |
31 | auto pWallet = std::make_shared<CWallet>(path); | |
32 | ASSERT_EQ(DB_LOAD_OK, pWallet->LoadWallet(fFirstRun)); | |
33 | pWallet->TopUpKeyPool(); | |
88fd8101 | 34 | std::cout << "Test wallet file path: " << path << std::endl; |
db0f9315 S |
35 | |
36 | int numKeys = 48; | |
37 | std::vector<CPubKey> pubkeys; | |
38 | pubkeys.resize(3); | |
39 | CPubKey newKey; | |
40 | std::vector<std::string> addresses; | |
241867b1 | 41 | for (int i = 0; i < numKeys; i++) { |
db0f9315 S |
42 | ASSERT_TRUE(pWallet->GetKeyFromPool(newKey)); |
43 | pubkeys[0] = newKey; | |
44 | ASSERT_TRUE(pWallet->GetKeyFromPool(newKey)); | |
45 | pubkeys[1] = newKey; | |
46 | ASSERT_TRUE(pWallet->GetKeyFromPool(newKey)); | |
47 | pubkeys[2] = newKey; | |
48 | CScript result = GetScriptForMultisig(2, pubkeys); | |
49 | ASSERT_FALSE(result.size() > MAX_SCRIPT_ELEMENT_SIZE); | |
50 | CScriptID innerID(result); | |
51 | std::string address = CBitcoinAddress(innerID).ToString(); | |
52 | addresses.push_back(address); | |
53 | } | |
54 | ||
55 | // Print out the addresses, 4 on each line. | |
56 | std::string s = "vFoundersRewardAddress = {\n"; | |
57 | int i=0; | |
58 | int colsPerRow = 4; | |
59 | ASSERT_TRUE(numKeys % colsPerRow == 0); | |
60 | int numRows = numKeys/colsPerRow; | |
61 | for (int row=0; row<numRows; row++) { | |
62 | s += " "; | |
63 | for (int col=0; col<colsPerRow; col++) { | |
64 | s += "\"" + addresses[i++] + "\", "; | |
65 | } | |
66 | s += "\n"; | |
67 | } | |
68 | s += " };"; | |
69 | std::cout << s << std::endl; | |
88fd8101 S |
70 | |
71 | pWallet->Flush(true); | |
db0f9315 S |
72 | } |
73 | #endif | |
74 | ||
75 | ||
3b30d836 | 76 | // Utility method to check the number of unique addresses from height 1 to maxHeight |
241867b1 S |
77 | void checkNumberOfUniqueAddresses(int nUnique) { |
78 | int maxHeight = Params().GetConsensus().GetLastFoundersRewardBlockHeight(); | |
3b30d836 | 79 | std::set<std::string> addresses; |
241867b1 | 80 | for (int i = 1; i <= maxHeight; i++) { |
3b30d836 S |
81 | addresses.insert(Params().GetFoundersRewardAddressAtHeight(i)); |
82 | } | |
241867b1 | 83 | ASSERT_TRUE(addresses.size() == nUnique); |
3b30d836 | 84 | } |
db0f9315 | 85 | |
3b30d836 S |
86 | |
87 | TEST(founders_reward_test, general) { | |
db0f9315 S |
88 | SelectParams(CBaseChainParams::TESTNET); |
89 | ||
90 | CChainParams params = Params(); | |
91 | ||
92 | // For Testnet, the first address is derived from the old script. | |
93 | // FOUNDERS_REWARD_SCRIPT = a9146708e6670db0b950dac68031025cc5b63213a49187 | |
94 | // address = 2N2e2FRfP9D1dRN1oRWkH7pbFM69eGNAuQ4 | |
3b30d836 S |
95 | EXPECT_EQ(params.GetFoundersRewardScriptAtHeight(1), ParseHex("a9146708e6670db0b950dac68031025cc5b63213a49187")); |
96 | EXPECT_EQ(params.GetFoundersRewardAddressAtHeight(1), "2N2e2FRfP9D1dRN1oRWkH7pbFM69eGNAuQ4"); | |
db0f9315 S |
97 | |
98 | int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); | |
99 | ||
100 | // If the block height parameter is out of bounds, there is an assert. | |
3b30d836 S |
101 | EXPECT_DEATH(params.GetFoundersRewardScriptAtHeight(0), "nHeight"); |
102 | EXPECT_DEATH(params.GetFoundersRewardScriptAtHeight(maxHeight+1), "nHeight"); | |
103 | EXPECT_DEATH(params.GetFoundersRewardAddressAtHeight(0), "nHeight"); | |
104 | EXPECT_DEATH(params.GetFoundersRewardAddressAtHeight(maxHeight+1), "nHeight"); | |
db0f9315 S |
105 | } |
106 | ||
107 | ||
108 | #define NUM_MAINNET_FOUNDER_ADDRESSES 48 | |
109 | ||
110 | TEST(founders_reward_test, mainnet) { | |
111 | SelectParams(CBaseChainParams::MAIN); | |
241867b1 | 112 | checkNumberOfUniqueAddresses(NUM_MAINNET_FOUNDER_ADDRESSES); |
3b30d836 S |
113 | } |
114 | ||
115 | ||
116 | #define NUM_TESTNET_FOUNDER_ADDRESSES 48 | |
117 | ||
118 | TEST(founders_reward_test, testnet) { | |
119 | SelectParams(CBaseChainParams::TESTNET); | |
241867b1 | 120 | checkNumberOfUniqueAddresses(NUM_TESTNET_FOUNDER_ADDRESSES); |
db0f9315 S |
121 | } |
122 | ||
123 | ||
124 | #define NUM_REGTEST_FOUNDER_ADDRESSES 1 | |
125 | ||
126 | TEST(founders_reward_test, regtest) { | |
127 | SelectParams(CBaseChainParams::REGTEST); | |
241867b1 | 128 | checkNumberOfUniqueAddresses(NUM_REGTEST_FOUNDER_ADDRESSES); |
db0f9315 S |
129 | } |
130 | ||
131 | ||
132 | ||
133 | // Test that 10% founders reward is fully rewarded after the first halving and slow start shift. | |
134 | // On Mainnet, this would be 2,100,000 ZEC after 850,000 blocks (840,000 + 10,000). | |
135 | TEST(founders_reward_test, slow_start_subsidy) { | |
136 | SelectParams(CBaseChainParams::MAIN); | |
137 | CChainParams params = Params(); | |
138 | ||
139 | int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); | |
140 | CAmount totalSubsidy = 0; | |
241867b1 S |
141 | for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { |
142 | CAmount nSubsidy = GetBlockSubsidy(nHeight, params.GetConsensus()) / 5; | |
db0f9315 S |
143 | totalSubsidy += nSubsidy; |
144 | } | |
145 | ||
146 | ASSERT_TRUE(totalSubsidy == MAX_MONEY/10.0); | |
147 | } | |
3b30d836 S |
148 | |
149 | ||
1a21a25e S |
150 | // For use with mainnet and testnet which each have 48 addresses. |
151 | // Verify the number of rewards each individual address receives. | |
152 | void verifyNumberOfRewards() { | |
3b30d836 | 153 | CChainParams params = Params(); |
241867b1 | 154 | int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); |
3b30d836 | 155 | std::multiset<std::string> ms; |
241867b1 | 156 | for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { |
3b30d836 S |
157 | ms.insert(params.GetFoundersRewardAddressAtHeight(nHeight)); |
158 | } | |
159 | ||
160 | ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(0)) == 17708); | |
161 | for (int i = 1; i <= 46; i++) { | |
162 | ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(i)) == 17709); | |
163 | } | |
164 | ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(47)) == 17677); | |
3b30d836 S |
165 | } |
166 | ||
1a21a25e S |
167 | // Verify the number of rewards going to each mainnet address |
168 | TEST(founders_reward_test, per_address_reward_mainnet) { | |
169 | SelectParams(CBaseChainParams::MAIN); | |
170 | verifyNumberOfRewards(); | |
171 | } | |
172 | ||
173 | // Verify the number of rewards going to each testnet address | |
174 | TEST(founders_reward_test, per_address_reward_testnet) { | |
175 | SelectParams(CBaseChainParams::TESTNET); | |
176 | verifyNumberOfRewards(); | |
177 | } |