Electroneum
block_reward.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 #include "gtest/gtest.h"
33 
35 
36 using namespace cryptonote;
37 
38 namespace
39 {
40  //--------------------------------------------------------------------------------------------------------------------
41  class block_reward_and_already_generated_coins : public ::testing::Test
42  {
43  protected:
44  static const size_t current_block_weight = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 / 2;
45 
46  bool m_block_not_too_big;
47  uint64_t m_block_reward;
49  };
50 
51  #define TEST_ALREADY_GENERATED_COINS(already_generated_coins, expected_reward) \
52  median = (already_generated_coins == 2002716) ? 1 : 0; \
53  m_block_not_too_big = get_block_reward(median, current_block_weight, already_generated_coins, m_block_reward,1,0); \
54  ASSERT_TRUE(m_block_not_too_big); \
55  ASSERT_EQ(m_block_reward, expected_reward);
56 
57  TEST_F(block_reward_and_already_generated_coins, handles_first_values)
58  {
59  /* NB the result of Test#1 is a consequence of how the premine was implemented without */
60  /* a complimentary change to the code that creates the genesis block and stores its data. */
61  /* Premined block must also be tested with median > 0 because of its implementation in get_block_reward */
62  /* Test the first few blocks: */
64  TEST_ALREADY_GENERATED_COINS(m_block_reward, UINT64_C(1260000000000));
65  TEST_ALREADY_GENERATED_COINS(m_block_reward + 2002716 , UINT64_C(801084));
66  TEST_ALREADY_GENERATED_COINS(m_block_reward + 2002716 + 1260000000000, UINT64_C(801083));
67  /* Test some large, arbitrary number before FINAL_SUBSIDY_PER_MINUTE is reached */
68  TEST_ALREADY_GENERATED_COINS(1860000000000, UINT64_C(228881));
69  }
70 
71  TEST_F(block_reward_and_already_generated_coins, correctly_steps_from_2_to_1)
72  {
76  }
77 
78  TEST_F(block_reward_and_already_generated_coins, handles_max)
79  {
83  }
84 
85  //--------------------------------------------------------------------------------------------------------------------
86  class block_reward_and_current_block_weight : public ::testing::Test
87  {
88  protected:
89  virtual void SetUp()
90  {
91  m_block_not_too_big = get_block_reward(0, 0, already_generated_coins, m_standard_block_reward, 1, 0);
92  ASSERT_TRUE(m_block_not_too_big);
94  }
95 
96  void do_test(size_t median_block_weight, size_t current_block_weight)
97  {
98  m_block_not_too_big = get_block_reward(median_block_weight, current_block_weight, already_generated_coins, m_block_reward, 1, 0);
99  }
100 
101  static const uint64_t already_generated_coins = 1260000000000;
102 
103  bool m_block_not_too_big;
104  uint64_t m_block_reward;
105  uint64_t m_standard_block_reward;
106  };
107 
108  TEST_F(block_reward_and_current_block_weight, handles_block_weight_less_relevance_level)
109  {
111  ASSERT_TRUE(m_block_not_too_big);
112  ASSERT_EQ(m_block_reward, m_standard_block_reward);
113  }
114 
115  TEST_F(block_reward_and_current_block_weight, handles_block_weight_eq_relevance_level)
116  {
118  ASSERT_TRUE(m_block_not_too_big);
119  ASSERT_EQ(m_block_reward, m_standard_block_reward);
120  }
121 
122  TEST_F(block_reward_and_current_block_weight, handles_block_weight_gt_relevance_level)
123  {
125  ASSERT_TRUE(m_block_not_too_big);
126  ASSERT_LT(m_block_reward, m_standard_block_reward);
127  }
128 
129  TEST_F(block_reward_and_current_block_weight, handles_block_weight_less_2_relevance_level)
130  {
132  ASSERT_TRUE(m_block_not_too_big);
133  ASSERT_LT(m_block_reward, m_standard_block_reward);
134  ASSERT_LT(0, m_block_reward);
135  }
136 
137  TEST_F(block_reward_and_current_block_weight, handles_block_weight_eq_2_relevance_level)
138  {
140  ASSERT_TRUE(m_block_not_too_big);
141  ASSERT_EQ(0, m_block_reward);
142  }
143 
144  TEST_F(block_reward_and_current_block_weight, handles_block_weight_gt_2_relevance_level)
145  {
147  ASSERT_FALSE(m_block_not_too_big);
148  }
149 
150 #ifdef __x86_64__ // For 64-bit systems only, because block size is limited to size_t.
151  TEST_F(block_reward_and_current_block_weight, fails_on_huge_median_size)
152  {
153 #if !defined(NDEBUG)
154  size_t huge_size = std::numeric_limits<uint32_t>::max() + UINT64_C(2);
155  ASSERT_DEATH(do_test(huge_size, huge_size + 1), "");
156 #endif
157  }
158 
159  TEST_F(block_reward_and_current_block_weight, fails_on_huge_block_weight)
160  {
161 #if !defined(NDEBUG)
162  size_t huge_size = std::numeric_limits<uint32_t>::max() + UINT64_C(2);
163  ASSERT_DEATH(do_test(huge_size - 2, huge_size), "");
164 #endif
165  }
166 #endif // __x86_64__
167 
168  //--------------------------------------------------------------------------------------------------------------------
169  class block_reward_and_last_block_weights : public ::testing::Test
170  {
171  protected:
172  virtual void SetUp()
173  {
174  m_last_block_weights.push_back(3 * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1);
175  m_last_block_weights.push_back(5 * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1);
176  m_last_block_weights.push_back(7 * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1);
177  m_last_block_weights.push_back(11 * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1);
178  m_last_block_weights.push_back(13 * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1);
179 
180  m_last_block_weights_median = 7 * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1;
181 
182  m_block_not_too_big = get_block_reward(epee::misc_utils::median(m_last_block_weights), 0, already_generated_coins, m_standard_block_reward, 1, 0);
183  ASSERT_TRUE(m_block_not_too_big);
185  }
186 
187  void do_test(size_t current_block_weight)
188  {
189  m_block_not_too_big = get_block_reward(epee::misc_utils::median(m_last_block_weights), current_block_weight, already_generated_coins, m_block_reward, 1, 0);
190  }
191 
192  static const uint64_t already_generated_coins = 1260000000000;
193 
194  std::vector<size_t> m_last_block_weights;
195  uint64_t m_last_block_weights_median;
196  bool m_block_not_too_big;
197  uint64_t m_block_reward;
198  uint64_t m_standard_block_reward;
199  };
200 
201  TEST_F(block_reward_and_last_block_weights, handles_block_weight_less_median)
202  {
203  do_test(m_last_block_weights_median - 1);
204  ASSERT_TRUE(m_block_not_too_big);
205  ASSERT_EQ(m_block_reward, m_standard_block_reward);
206  }
207 
208  TEST_F(block_reward_and_last_block_weights, handles_block_weight_eq_median)
209  {
210  do_test(m_last_block_weights_median);
211  ASSERT_TRUE(m_block_not_too_big);
212  ASSERT_EQ(m_block_reward, m_standard_block_reward);
213  }
214 
215  TEST_F(block_reward_and_last_block_weights, handles_block_weight_gt_median)
216  {
217  do_test(m_last_block_weights_median + 1);
218  ASSERT_TRUE(m_block_not_too_big);
219  ASSERT_LT(m_block_reward, m_standard_block_reward);
220  }
221 
222  TEST_F(block_reward_and_last_block_weights, handles_block_weight_less_2_medians)
223  {
224  do_test(2 * m_last_block_weights_median - 1);
225  ASSERT_TRUE(m_block_not_too_big);
226  ASSERT_LT(m_block_reward, m_standard_block_reward);
227  ASSERT_LT(0, m_block_reward);
228  }
229 
230  TEST_F(block_reward_and_last_block_weights, handles_block_weight_eq_2_medians)
231  {
232  do_test(2 * m_last_block_weights_median);
233  ASSERT_TRUE(m_block_not_too_big);
234  ASSERT_EQ(0, m_block_reward);
235  }
236 
237  TEST_F(block_reward_and_last_block_weights, handles_block_weight_gt_2_medians)
238  {
239  do_test(2 * m_last_block_weights_median + 1);
240  ASSERT_FALSE(m_block_not_too_big);
241  }
242 
243  TEST_F(block_reward_and_last_block_weights, calculates_correctly)
244  {
245  ASSERT_EQ(0, m_last_block_weights_median % 8);
246 
247  do_test(m_last_block_weights_median * 9 / 8);
248  ASSERT_TRUE(m_block_not_too_big);
249  ASSERT_EQ(m_block_reward, m_standard_block_reward * 63 / 64);
250 
251  // 3/2 = 12/8
252  do_test(m_last_block_weights_median * 3 / 2);
253  ASSERT_TRUE(m_block_not_too_big);
254  ASSERT_EQ(m_block_reward, m_standard_block_reward * 3 / 4);
255 
256  do_test(m_last_block_weights_median * 15 / 8);
257  ASSERT_TRUE(m_block_not_too_big);
258  ASSERT_EQ(m_block_reward, m_standard_block_reward * 15 / 64);
259  }
260 }
#define TEST_ALREADY_GENERATED_COINS(already_generated_coins, expected_reward)
#define ETN_SUPPLY
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
unsigned __int64 uint64_t
Definition: stdint.h:136
#define UINT64_C(val)
Definition: stdint.h:284
#define ASSERT_LT(val1, val2)
Definition: gtest.h:1968
type_vec_type median(std::vector< type_vec_type > &v)
#define TEST_F(test_fixture, test_name)
Definition: gtest.h:2216
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
#define FINAL_SUBSIDY_PER_MINUTE
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version, uint64_t current_block_height, network_type nettype)
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1