Electroneum
hardfork.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 <algorithm>
33 #include "gtest/gtest.h"
34 
38 #include "blockchain_db/testdb.h"
39 
40 using namespace cryptonote;
41 
42 #define BLOCKS_PER_YEAR 525960
43 #define SECONDS_PER_YEAR 31557600
44 
45 namespace
46 {
47 
48 class TestDB: public cryptonote::BaseTestDB {
49 public:
50  virtual uint64_t height() const override { return blocks.size(); }
51  virtual void add_block( const block& blk
52  , size_t block_weight
53  , uint64_t long_term_block_weight
54  , const difficulty_type& cumulative_difficulty
55  , const uint64_t& coins_generated
56  , uint64_t num_rct_outs
57  , const crypto::hash& blk_hash
58  ) override {
59  blocks.push_back(blk);
60  }
61  virtual void remove_block() override { blocks.pop_back(); }
62  virtual block get_block_from_height(const uint64_t& height) const override {
63  return blocks.at(height);
64  }
65  virtual void set_hard_fork_version(uint64_t height, uint8_t version) override {
66  if (versions.size() <= height)
67  versions.resize(height+1);
68  versions[height] = version;
69  }
70  virtual uint8_t get_hard_fork_version(uint64_t height) const override {
71  return versions.at(height);
72  }
73 
74 private:
75  std::vector<block> blocks;
76  std::deque<uint8_t> versions;
77 };
78 
79 }
80 
81 static cryptonote::block mkblock(uint8_t version, uint8_t vote)
82 {
85  b.minor_version = vote;
86  return b;
87 }
88 
89 static cryptonote::block mkblock(const HardFork &hf, uint64_t height, uint8_t vote)
90 {
92  b.major_version = hf.get(height);
93  b.minor_version = vote;
94  return b;
95 }
96 
97 TEST(major, Only)
98 {
99  TestDB db;
100  HardFork hf(db, 1, 0, 0, 0, 1, 0); // no voting
101 
102  // v h t
103  ASSERT_TRUE(hf.add_fork(1, 0, 0));
104  ASSERT_TRUE(hf.add_fork(2, 2, 1));
105  hf.init();
106 
107  // block height 0, only version 1 is accepted
108  ASSERT_FALSE(hf.add(mkblock(0, 2), 0));
109  ASSERT_FALSE(hf.add(mkblock(2, 2), 0));
110  ASSERT_TRUE(hf.add(mkblock(1, 2), 0));
111  db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, crypto::hash());
112 
113  // block height 1, only version 1 is accepted
114  ASSERT_FALSE(hf.add(mkblock(0, 2), 1));
115  ASSERT_FALSE(hf.add(mkblock(2, 2), 1));
116  ASSERT_TRUE(hf.add(mkblock(1, 2), 1));
117  db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, crypto::hash());
118 
119  // block height 2, only version 2 is accepted
120  ASSERT_FALSE(hf.add(mkblock(0, 2), 2));
121  ASSERT_FALSE(hf.add(mkblock(1, 2), 2));
122  ASSERT_FALSE(hf.add(mkblock(3, 2), 2));
123  ASSERT_TRUE(hf.add(mkblock(2, 2), 2));
124  db.add_block(mkblock(2, 1), 0, 0, 0, 0, 0, crypto::hash());
125 }
126 
127 TEST(empty_hardforks, Success)
128 {
129  TestDB db;
130  HardFork hf(db);
131 
132  ASSERT_TRUE(hf.add_fork(1, 0, 0));
133  hf.init();
135  ASSERT_TRUE(hf.get_state(time(NULL) + 3600*24*400) == HardFork::Ready);
136 
137  for (uint64_t h = 0; h <= 10; ++h) {
138  db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, crypto::hash());
139  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
140  }
141  ASSERT_EQ(hf.get(0), 1);
142  ASSERT_EQ(hf.get(1), 1);
143  ASSERT_EQ(hf.get(10), 1);
144 }
145 
146 TEST(ordering, Success)
147 {
148  TestDB db;
149  HardFork hf(db);
150 
151  ASSERT_TRUE(hf.add_fork(2, 2, 1));
152  ASSERT_FALSE(hf.add_fork(3, 3, 1));
153  ASSERT_FALSE(hf.add_fork(3, 2, 2));
154  ASSERT_FALSE(hf.add_fork(2, 3, 2));
155  ASSERT_TRUE(hf.add_fork(3, 10, 2));
156  ASSERT_TRUE(hf.add_fork(4, 20, 3));
157  ASSERT_FALSE(hf.add_fork(5, 5, 4));
158 }
159 
160 TEST(check_for_height, Success)
161 {
162  TestDB db;
163  HardFork hf(db, 1, 0, 0, 0, 1, 0); // no voting
164 
165  ASSERT_TRUE(hf.add_fork(1, 0, 0));
166  ASSERT_TRUE(hf.add_fork(2, 5, 1));
167  hf.init();
168 
169  for (uint64_t h = 0; h <= 4; ++h) {
170  ASSERT_TRUE(hf.check_for_height(mkblock(1, 1), h));
171  ASSERT_FALSE(hf.check_for_height(mkblock(2, 2), h)); // block version is too high
172  db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, crypto::hash());
173  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
174  }
175 
176  for (uint64_t h = 5; h <= 10; ++h) {
177  ASSERT_FALSE(hf.check_for_height(mkblock(1, 1), h)); // block version is too low
178  ASSERT_TRUE(hf.check_for_height(mkblock(2, 2), h));
179  db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, crypto::hash());
180  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
181  }
182 }
183 
184 TEST(get, next_version)
185 {
186  TestDB db;
187  HardFork hf(db);
188 
189  ASSERT_TRUE(hf.add_fork(1, 0, 0));
190  ASSERT_TRUE(hf.add_fork(2, 5, 1));
191  ASSERT_TRUE(hf.add_fork(4, 10, 2));
192  hf.init();
193 
194  for (uint64_t h = 0; h <= 4; ++h) {
195  ASSERT_EQ(2, hf.get_next_version());
196  db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, crypto::hash());
197  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
198  }
199 
200  for (uint64_t h = 5; h <= 9; ++h) {
201  ASSERT_EQ(4, hf.get_next_version());
202  db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, crypto::hash());
203  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
204  }
205 
206  for (uint64_t h = 10; h <= 15; ++h) {
207  ASSERT_EQ(4, hf.get_next_version());
208  db.add_block(mkblock(hf, h, 4), 0, 0, 0, 0, 0, crypto::hash());
209  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
210  }
211 }
212 
213 TEST(states, Success)
214 {
215  TestDB db;
216  HardFork hf(db);
217 
218  ASSERT_TRUE(hf.add_fork(1, 0, 0));
220 
226 
228 
234 }
235 
236 TEST(steps_asap, Success)
237 {
238  TestDB db;
239  HardFork hf(db, 1,0,1,1,1);
240 
241  // v h t
242  ASSERT_TRUE(hf.add_fork(1, 0, 0));
243  ASSERT_TRUE(hf.add_fork(4, 2, 1));
244  ASSERT_TRUE(hf.add_fork(7, 4, 2));
245  ASSERT_TRUE(hf.add_fork(9, 6, 3));
246  hf.init();
247 
248  for (uint64_t h = 0; h < 10; ++h) {
249  db.add_block(mkblock(hf, h, 9), 0, 0, 0, 0, 0, crypto::hash());
250  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
251  }
252 
253  ASSERT_EQ(hf.get(0), 1);
254  ASSERT_EQ(hf.get(1), 1);
255  ASSERT_EQ(hf.get(2), 4);
256  ASSERT_EQ(hf.get(3), 4);
257  ASSERT_EQ(hf.get(4), 7);
258  ASSERT_EQ(hf.get(5), 7);
259  ASSERT_EQ(hf.get(6), 9);
260  ASSERT_EQ(hf.get(7), 9);
261  ASSERT_EQ(hf.get(8), 9);
262  ASSERT_EQ(hf.get(9), 9);
263 }
264 
265 TEST(steps_1, Success)
266 {
267  TestDB db;
268  HardFork hf(db, 1,0,1,1,1);
269 
270  ASSERT_TRUE(hf.add_fork(1, 0, 0));
271  for (int n = 1 ; n < 10; ++n)
272  ASSERT_TRUE(hf.add_fork(n+1, n, n));
273  hf.init();
274 
275  for (uint64_t h = 0 ; h < 10; ++h) {
276  db.add_block(mkblock(hf, h, h+1), 0, 0, 0, 0, 0, crypto::hash());
277  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
278  }
279 
280  for (uint64_t h = 0; h < 10; ++h) {
281  ASSERT_EQ(hf.get(h), std::max(1,(int)h));
282  }
283 }
284 
285 TEST(reorganize, Same)
286 {
287  for (int history = 1; history <= 12; ++history) {
288  TestDB db;
289  HardFork hf(db, 1, 0, 1, 1, history, 100);
290 
291  // v h t
292  ASSERT_TRUE(hf.add_fork(1, 0, 0));
293  ASSERT_TRUE(hf.add_fork(4, 2, 1));
294  ASSERT_TRUE(hf.add_fork(7, 4, 2));
295  ASSERT_TRUE(hf.add_fork(9, 6, 3));
296  hf.init();
297 
298  // index 0 1 2 3 4 5 6 7 8 9
299  static const uint8_t block_versions[] = { 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
300  for (uint64_t h = 0; h < 20; ++h) {
301  db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
302  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
303  }
304 
305  for (uint64_t rh = 0; rh < 20; ++rh) {
307  for (int hh = 0; hh < 20; ++hh) {
308  uint8_t version = hh >= history ? block_versions[hh - history] : 1;
309  ASSERT_EQ(hf.get(hh), version);
310  }
311  }
312  }
313 }
314 
315 TEST(reorganize, Changed)
316 {
317  TestDB db;
318  HardFork hf(db, 1, 0, 1, 1, 4, 100);
319 
320  // v h t
321  ASSERT_TRUE(hf.add_fork(1, 0, 0));
322  ASSERT_TRUE(hf.add_fork(4, 2, 1));
323  ASSERT_TRUE(hf.add_fork(7, 4, 2));
324  ASSERT_TRUE(hf.add_fork(9, 6, 3));
325  hf.init();
326 
327  // fork 4 7 9
328  // index 0 1 2 3 4 5 6 7 8 9
329  static const uint8_t block_versions[] = { 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
330  static const uint8_t expected_versions[] = { 1, 1, 1, 1, 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9 };
331  for (uint64_t h = 0; h < 16; ++h) {
332  db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
333  ASSERT_TRUE (hf.add(db.get_block_from_height(h), h));
334  }
335 
336  for (uint64_t rh = 0; rh < 16; ++rh) {
338  for (int hh = 0; hh < 16; ++hh) {
339  ASSERT_EQ(hf.get(hh), expected_versions[hh]);
340  }
341  }
342 
343  // delay a bit for 9, and go back to 1 to check it stays at 9
344  static const uint8_t block_versions_new[] = { 1, 1, 4, 4, 7, 7, 4, 7, 7, 7, 9, 9, 9, 9, 9, 1 };
345  static const uint8_t expected_versions_new[] = { 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 7, 7, 7, 9, 9 };
346  for (uint64_t h = 3; h < 16; ++h) {
347  db.remove_block();
348  }
349  ASSERT_EQ(db.height(), 3);
351  for (uint64_t h = 3; h < 16; ++h) {
352  db.add_block(mkblock(hf, h, block_versions_new[h]), 0, 0, 0, 0, 0, crypto::hash());
353  bool ret = hf.add(db.get_block_from_height(h), h);
354  ASSERT_EQ (ret, h < 15);
355  }
356  db.remove_block(); // last block added to the blockchain, but not hf
357  ASSERT_EQ(db.height(), 15);
358  for (int hh = 0; hh < 15; ++hh) {
359  ASSERT_EQ(hf.get(hh), expected_versions_new[hh]);
360  }
361 }
362 
363 TEST(voting, threshold)
364 {
365  for (int threshold = 87; threshold <= 88; ++threshold) {
366  TestDB db;
367  HardFork hf(db, 1, 0, 1, 1, 8, threshold);
368 
369  // v h t
370  ASSERT_TRUE(hf.add_fork(1, 0, 0));
371  ASSERT_TRUE(hf.add_fork(2, 2, 1));
372  hf.init();
373 
374  for (uint64_t h = 0; h <= 8; ++h) {
375  uint8_t v = 1 + !!(h % 8);
376  db.add_block(mkblock(hf, h, v), 0, 0, 0, 0, 0, crypto::hash());
377  bool ret = hf.add(db.get_block_from_height(h), h);
378  if (h >= 8 && threshold == 87) {
379  // for threshold 87, we reach the treshold at height 7, so from height 8, hard fork to version 2, but 8 tries to add 1
380  ASSERT_FALSE(ret);
381  }
382  else {
383  // for threshold 88, we never reach the threshold
384  ASSERT_TRUE(ret);
385  uint8_t expected = threshold == 88 ? 1 : h < 8 ? 1 : 2;
386  ASSERT_EQ(hf.get(h), expected);
387  }
388  }
389  }
390 }
391 
392 TEST(voting, different_thresholds)
393 {
394  for (int threshold = 87; threshold <= 88; ++threshold) {
395  TestDB db;
396  HardFork hf(db, 1, 0, 1, 1, 4, 50); // window size 4
397 
398  // v h t
399  ASSERT_TRUE(hf.add_fork(1, 0, 0));
400  ASSERT_TRUE(hf.add_fork(2, 5, 0, 1)); // asap
401  ASSERT_TRUE(hf.add_fork(3, 10, 100, 2)); // all votes
402  ASSERT_TRUE(hf.add_fork(4, 15, 3)); // default 50% votes
403  hf.init();
404 
405  // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
406  static const uint8_t block_versions[] = { 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 };
407  static const uint8_t expected_versions[] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
408 
409  for (uint64_t h = 0; h < sizeof(block_versions) / sizeof(block_versions[0]); ++h) {
410  db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
411  bool ret = hf.add(db.get_block_from_height(h), h);
412  ASSERT_EQ(ret, true);
413  }
414  for (uint64_t h = 0; h < sizeof(expected_versions) / sizeof(expected_versions[0]); ++h) {
415  ASSERT_EQ(hf.get(h), expected_versions[h]);
416  }
417  }
418 }
419 
420 TEST(voting, info)
421 {
422  TestDB db;
423  HardFork hf(db, 1, 0, 1, 1, 4, 50); // window size 4, default threshold 50%
424 
425  // v h ts
426  ASSERT_TRUE(hf.add_fork(1, 0, 0));
427  // v h thr ts
428  ASSERT_TRUE(hf.add_fork(2, 5, 0, 1)); // asap
429  ASSERT_TRUE(hf.add_fork(3, 10, 100, 2)); // all votes
430  // v h ts
431  ASSERT_TRUE(hf.add_fork(4, 15, 3)); // default 50% votes
432  hf.init();
433 
434  // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
435  static const uint8_t block_versions[] = { 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 };
436  static const uint8_t expected_versions[] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
437  static const uint8_t expected_thresholds[] = { 0, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 2, 2, 2, 2 };
438 
439  for (uint64_t h = 0; h < sizeof(block_versions) / sizeof(block_versions[0]); ++h) {
440  uint32_t window, votes, threshold;
441  uint64_t earliest_height;
442  uint8_t voting;
443 
444  ASSERT_TRUE(hf.get_voting_info(1, window, votes, threshold, earliest_height, voting));
445  ASSERT_EQ(std::min<uint64_t>(h, 4), votes);
446  ASSERT_EQ(0, earliest_height);
447 
448  ASSERT_EQ(hf.get_current_version() >= 2, hf.get_voting_info(2, window, votes, threshold, earliest_height, voting));
449  ASSERT_EQ(std::min<uint64_t>(h <= 3 ? 0 : h - 3, 4), votes);
450  ASSERT_EQ(5, earliest_height);
451 
452  ASSERT_EQ(hf.get_current_version() >= 3, hf.get_voting_info(3, window, votes, threshold, earliest_height, voting));
453  ASSERT_EQ(std::min<uint64_t>(h <= 8 ? 0 : h - 8, 4), votes);
454  ASSERT_EQ(10, earliest_height);
455 
456  ASSERT_EQ(hf.get_current_version() == 4, hf.get_voting_info(4, window, votes, threshold, earliest_height, voting));
457  ASSERT_EQ(std::min<uint64_t>(h <= 14 ? 0 : h - 14, 4), votes);
458  ASSERT_EQ(15, earliest_height);
459 
460  ASSERT_EQ(std::min<uint64_t>(h, 4), window);
461  ASSERT_EQ(expected_thresholds[h], threshold);
462  ASSERT_EQ(4, voting);
463 
464  db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
465  ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
466  }
467 }
468 
469 TEST(new_blocks, denied)
470 {
471  TestDB db;
472  HardFork hf(db, 1, 0, 1, 1, 4, 50);
473 
474  // v h t
475  ASSERT_TRUE(hf.add_fork(1, 0, 0));
476  ASSERT_TRUE(hf.add_fork(2, 2, 1));
477  hf.init();
478 
479  ASSERT_TRUE(hf.add(mkblock(1, 1), 0));
480  ASSERT_TRUE(hf.add(mkblock(1, 1), 1));
481  ASSERT_TRUE(hf.add(mkblock(1, 1), 2));
482  ASSERT_TRUE(hf.add(mkblock(1, 2), 3));
483  ASSERT_TRUE(hf.add(mkblock(1, 1), 4));
484  ASSERT_TRUE(hf.add(mkblock(1, 1), 5));
485  ASSERT_TRUE(hf.add(mkblock(1, 1), 6));
486  ASSERT_TRUE(hf.add(mkblock(1, 2), 7));
487  ASSERT_TRUE(hf.add(mkblock(1, 2), 8)); // we reach 50% of the last 4
488  ASSERT_FALSE(hf.add(mkblock(2, 1), 9)); // so this one can't get added
489  ASSERT_TRUE(hf.add(mkblock(2, 2), 9));
490 }
491 
492 TEST(new_version, early)
493 {
494  TestDB db;
495  HardFork hf(db, 1, 0, 1, 1, 4, 50);
496 
497  // v h t
498  ASSERT_TRUE(hf.add_fork(1, 0, 0));
499  ASSERT_TRUE(hf.add_fork(2, 4, 1));
500  hf.init();
501 
502  ASSERT_TRUE(hf.add(mkblock(1, 2), 0));
503  ASSERT_TRUE(hf.add(mkblock(1, 2), 1)); // we have enough votes already
504  ASSERT_TRUE(hf.add(mkblock(1, 2), 2));
505  ASSERT_TRUE(hf.add(mkblock(1, 1), 3)); // we accept a previous version because we did not switch, even with all the votes
506  ASSERT_TRUE(hf.add(mkblock(2, 2), 4)); // but have to wait for the declared height anyway
507  ASSERT_TRUE(hf.add(mkblock(2, 2), 5));
508  ASSERT_FALSE(hf.add(mkblock(2, 1), 6)); // we don't accept 1 anymore
509  ASSERT_TRUE(hf.add(mkblock(2, 2), 7)); // but we do accept 2
510 }
511 
512 TEST(reorganize, changed)
513 {
514  TestDB db;
515  HardFork hf(db, 1, 0, 1, 1, 4, 50);
516 
517  // v h t
518  ASSERT_TRUE(hf.add_fork(1, 0, 0));
519  ASSERT_TRUE(hf.add_fork(2, 2, 1));
520  ASSERT_TRUE(hf.add_fork(3, 5, 2));
521  ASSERT_TRUE(hf.add_fork(4, 555, 222));
522  hf.init();
523 
524 #define ADD(v, h, a) \
525  do { \
526  cryptonote::block b = mkblock(hf, h, v); \
527  db.add_block(b, 0, 0, 0, 0, 0, crypto::hash()); \
528  ASSERT_##a(hf.add(b, h)); \
529  } while(0)
530 #define ADD_TRUE(v, h) ADD(v, h, TRUE)
531 #define ADD_FALSE(v, h) ADD(v, h, FALSE)
532 
533  ADD_TRUE(1, 0);
534  ADD_TRUE(1, 1);
535  ADD_TRUE(2, 2);
536  ADD_TRUE(2, 3); // switch to 2 here
537  ADD_TRUE(2, 4);
538  ADD_TRUE(2, 5);
539  ADD_TRUE(2, 6);
541  ADD_TRUE(3, 7);
542  ADD_TRUE(4, 8);
543  ADD_TRUE(4, 9);
545 
546  // pop a few blocks and check current version goes back down
547  db.remove_block();
550  db.remove_block();
553  db.remove_block();
555 
556  // add blocks again, but remaining at 2
557  ADD_TRUE(2, 7);
558  ADD_TRUE(2, 8);
559  ADD_TRUE(2, 9);
560  ASSERT_EQ(hf.get_current_version(), 2); // we did not bump to 3 this time
561 }
562 
563 TEST(get, higher)
564 {
565  TestDB db;
566  HardFork hf(db, 1, 0, 1, 1, 4, 50);
567 
568  // v h t
569  ASSERT_TRUE(hf.add_fork(1, 0, 0));
570  ASSERT_TRUE(hf.add_fork(2, 2, 1));
571  ASSERT_TRUE(hf.add_fork(3, 5, 2));
572  hf.init();
573 
574  ASSERT_EQ(hf.get_ideal_version(0), 1);
575  ASSERT_EQ(hf.get_ideal_version(1), 1);
576  ASSERT_EQ(hf.get_ideal_version(2), 2);
577  ASSERT_EQ(hf.get_ideal_version(3), 2);
578  ASSERT_EQ(hf.get_ideal_version(4), 2);
579  ASSERT_EQ(hf.get_ideal_version(5), 3);
580  ASSERT_EQ(hf.get_ideal_version(6), 3);
581  ASSERT_EQ(hf.get_ideal_version(7), 3);
582 }
583 
584 TEST(get, earliest_ideal_height)
585 {
586  TestDB db;
587  HardFork hf(db, 1, 0, 1, 1, 4, 50);
588 
589  // v h t
590  ASSERT_TRUE(hf.add_fork(1, 0, 0));
591  ASSERT_TRUE(hf.add_fork(2, 2, 1));
592  ASSERT_TRUE(hf.add_fork(5, 5, 2));
593  ASSERT_TRUE(hf.add_fork(6, 10, 3));
594  ASSERT_TRUE(hf.add_fork(9, 15, 4));
595  hf.init();
596 
606  ASSERT_EQ(hf.get_earliest_ideal_height_for_version(10), std::numeric_limits<uint64_t>::max());
607 }
608 
uint8_t get_current_version() const
returns the current version
Definition: hardfork.cpp:361
uint8_t get_next_version() const
returns the next version
Definition: hardfork.cpp:397
TEST(major, Only)
Definition: hardfork.cpp:97
static const time_t DEFAULT_FORKED_TIME
Definition: hardfork.h:49
uint64_t height
Definition: blockchain.cpp:91
void init()
initialize the object
Definition: hardfork.cpp:169
unsigned char uint8_t
Definition: stdint.h:124
static const time_t DEFAULT_UPDATE_TIME
Definition: hardfork.h:50
#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
time_t time
Definition: blockchain.cpp:93
unsigned int uint32_t
Definition: stdint.h:126
uint8_t get(uint64_t height) const
returns the hard fork version for the given block height
Definition: hardfork.cpp:348
bool add(const cryptonote::block &block, uint64_t height)
add a new block
Definition: hardfork.cpp:164
unsigned __int64 uint64_t
Definition: stdint.h:136
bool check_for_height(const cryptonote::block &block, uint64_t height) const
same as check, but for a particular height, rather than the top
Definition: hardfork.cpp:129
version
Supported socks variants.
Definition: socks.h:57
uint8_t get_ideal_version() const
returns the latest "ideal" version
Definition: hardfork.cpp:367
bool get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
returns information about current voting state
Definition: hardfork.cpp:409
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
#define BLOCKS_PER_YEAR
Definition: hardfork.cpp:42
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
uint64_t get_earliest_ideal_height_for_version(uint8_t version) const
returns the earliest block a given version may activate
Definition: hardfork.cpp:384
#define SECONDS_PER_YEAR
Definition: hardfork.cpp:43
State get_state(time_t t) const
returns current state at the given time
Definition: hardfork.cpp:327
POD_CLASS hash
Definition: hash.h:50
bool add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time)
add a new hardfork height
Definition: hardfork.cpp:74
bool reorganize_from_block_height(uint64_t height)
called when the blockchain is reorganized
Definition: hardfork.cpp:202
#define ADD_TRUE(v, h)
uint8_t threshold
Definition: blockchain.cpp:92