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