Electroneum
block_weight.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #define IN_UNIT_TESTS
30 
31 #include <stdio.h>
32 #include <math.h>
36 #include "blockchain_db/testdb.h"
37 
38 #define LONG_TERM_BLOCK_WEIGHT_WINDOW 5000
39 
40 enum test_t
41 {
42  test_max = 0,
43  test_lcg = 1,
44  test_min = 2,
45 };
46 
47 namespace
48 {
49 
50 class TestDB: public cryptonote::BaseTestDB
51 {
52 private:
53  struct block_t
54  {
55  size_t weight;
56  uint64_t long_term_weight;
57  };
58 
59 public:
60  TestDB() { m_open = true; }
61 
62  virtual void add_block( const cryptonote::block& blk
63  , size_t block_weight
64  , uint64_t long_term_block_weight
65  , const cryptonote::difficulty_type& cumulative_difficulty
66  , const uint64_t& coins_generated
67  , uint64_t num_rct_outs
68  , const crypto::hash& blk_hash
69  ) override {
70  blocks.push_back({block_weight, long_term_block_weight});
71  }
72  virtual uint64_t height() const override { return blocks.size(); }
73  virtual size_t get_block_weight(const uint64_t &h) const override { return blocks[h].weight; }
74  virtual uint64_t get_block_long_term_weight(const uint64_t &h) const override { return blocks[h].long_term_weight; }
75  virtual std::vector<uint64_t> get_block_weights(uint64_t start_height, size_t count) const override {
76  std::vector<uint64_t> ret;
77  ret.reserve(count);
78  while (count-- && start_height < blocks.size()) ret.push_back(blocks[start_height++].weight);
79  return ret;
80  }
81  virtual std::vector<uint64_t> get_long_term_block_weights(uint64_t start_height, size_t count) const override {
82  std::vector<uint64_t> ret;
83  ret.reserve(count);
84  while (count-- && start_height < blocks.size()) ret.push_back(blocks[start_height++].long_term_weight);
85  return ret;
86  }
87  virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const override {
88  crypto::hash hash = crypto::null_hash;
89  *(uint64_t*)&hash = height;
90  return hash;
91  }
92  virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const override {
93  uint64_t h = height();
94  crypto::hash top = crypto::null_hash;
95  if (h)
96  *(uint64_t*)&top = h - 1;
97  if (block_height)
98  *block_height = h - 1;
99  return top;
100  }
101  virtual void pop_block(cryptonote::block &blk, std::vector<cryptonote::transaction> &txs) override { blocks.pop_back(); }
102  virtual void set_hard_fork_version(uint64_t height, uint8_t version) override { if (height >= hf.size()) hf.resize(height + 1); hf[height] = version; }
103  virtual uint8_t get_hard_fork_version(uint64_t height) const override { if (height >= hf.size()) return 255; return hf[height]; }
104 
105 private:
106  std::vector<block_t> blocks;
107  std::vector<uint8_t> hf;
108 };
109 
110 }
111 
112 #define PREFIX_WINDOW(hf_version,window) \
113  std::unique_ptr<cryptonote::Blockchain> bc; \
114  cryptonote::tx_memory_pool txpool(*bc); \
115  bc.reset(new cryptonote::Blockchain(txpool)); \
116  struct get_test_options { \
117  const std::pair<uint8_t, uint64_t> hard_forks[3]; \
118  const cryptonote::test_options test_options = { \
119  hard_forks, \
120  window, \
121  }; \
122  get_test_options(): hard_forks{std::make_pair(1, (uint64_t)0), std::make_pair((uint8_t)hf_version, (uint64_t)LONG_TERM_BLOCK_WEIGHT_WINDOW), std::make_pair((uint8_t)0, (uint64_t)0)} {} \
123  } opts; \
124  cryptonote::Blockchain *blockchain = bc.get(); \
125  bool r = blockchain->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \
126  if (!r) \
127  { \
128  fprintf(stderr, "Failed to init blockchain\n"); \
129  exit(1); \
130  }
131 
132 #define PREFIX(hf_version) PREFIX_WINDOW(hf_version, LONG_TERM_BLOCK_WEIGHT_WINDOW)
133 
134 static uint32_t lcg_seed = 0;
135 
136 static uint32_t lcg()
137 {
138  lcg_seed = (lcg_seed * 0x100000001b3 + 0xcbf29ce484222325) & 0xffffffff;
139  return lcg_seed;
140 }
141 
142 static void test(test_t t, uint64_t blocks)
143 {
145 
146  for (uint64_t h = 0; h < LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
147  {
149  b.major_version = 1;
150  b.minor_version = 1;
151  bc->get_db().add_block(std::make_pair(b, ""), 300000, 300000, bc->get_db().height(), bc->get_db().height(), {});
152  if (!bc->update_next_cumulative_weight_limit())
153  {
154  fprintf(stderr, "Failed to update cumulative weight limit 1\n");
155  exit(1);
156  }
157  }
158 
159  for (uint64_t h = 0; h < blocks; ++h)
160  {
161  uint64_t w;
162  uint64_t effective_block_weight_median = bc->get_current_cumulative_block_weight_median();
163  switch (t)
164  {
165  case test_lcg:
166  {
167  uint32_t r = lcg();
168  int64_t wi = 90 + r % 500000 + 250000 + sin(h / 200.) * 350000;
169  w = wi < 90 ? 90 : wi;
170  break;
171  }
172  case test_max:
173  w = bc->get_current_cumulative_block_weight_limit();
174  break;
175  case test_min:
176  w = 90;
177  break;
178  default:
179  exit(1);
180  }
181  uint64_t ltw = bc->get_next_long_term_block_weight(w);
183  b.major_version = 10;
184  b.minor_version = 10;
185  bc->get_db().add_block(std::make_pair(std::move(b), ""), w, ltw, bc->get_db().height(), bc->get_db().height(), {});
186 
187  if (!bc->update_next_cumulative_weight_limit())
188  {
189  fprintf(stderr, "Failed to update cumulative weight limit\n");
190  exit(1);
191  }
192  std::cout << "H " << h << ", BW " << w << ", EMBW " << effective_block_weight_median << ", LTBW " << ltw << std::endl;
193  }
194 }
195 
196 int main()
197 {
198  TRY_ENTRY();
202  return 0;
203  CATCH_ENTRY_L0("main", 1);
204 }
#define LONG_TERM_BLOCK_WEIGHT_WINDOW
uint64_t height
Definition: blockchain.cpp:91
#define PREFIX(hf_version)
unsigned char uint8_t
Definition: stdint.h:124
int main()
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT
mdb_size_t count(MDB_cursor *cur)
test_t
#define TRY_ENTRY()
Definition: misc_log_ex.h:151
unsigned int uint32_t
Definition: stdint.h:126
unsigned __int64 uint64_t
Definition: stdint.h:136
version
Supported socks variants.
Definition: socks.h:57
const T & move(const T &t)
Definition: gtest-port.h:1317
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
signed __int64 int64_t
Definition: stdint.h:135
POD_CLASS hash
Definition: hash.h:50
#define CATCH_ENTRY_L0(lacation, return_val)
Definition: misc_log_ex.h:165