Electroneum
cryptonote_basic_impl.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 "include_base_utils.h"
33 using namespace epee;
34 
35 #include "cryptonote_basic_impl.h"
36 #include "string_tools.h"
40 #include "cryptonote_config.h"
41 #include "misc_language.h"
42 #include "common/base58.h"
43 #include "crypto/hash.h"
44 #include "int-util.h"
45 #include "common/dns_utils.h"
46 
47 #include <math.h>
48 
49 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
50 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "cn"
51 
52 namespace cryptonote {
53 
57 
59  FIELD(adr)
60  FIELD(payment_id)
62 
64  KV_SERIALIZE(adr)
65  KV_SERIALIZE(payment_id)
67  };
68 
69  /************************************************************************/
70  /* Cryptonote helper functions */
71  /************************************************************************/
72  //-----------------------------------------------------------------------------------------------
74  {
75  if (version < 2)
77  if (version < 5)
79  if (version < 8)
81  if (version < 10)
84  }
85  //-----------------------------------------------------------------------------------------------
86  size_t get_max_tx_size()
87  {
89  }
90  //-----------------------------------------------------------------------------------------------
91  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) {
92  static_assert(DIFFICULTY_TARGET%60==0,"difficulty target must be a multiple of 60");
93  static_assert(DIFFICULTY_TARGET_V6%60==0,"difficulty target V6 must be a multiple of 60");
94 
95  const int target = version >= 6 ? DIFFICULTY_TARGET_V6 : DIFFICULTY_TARGET;
96 
97  const int target_minutes = target / 60;
98 
99  uint64_t full_reward_zone = get_min_block_weight(version);
100 
101  const uint64_t premine = 1260000000000U;
102  if (median_weight > 0 && already_generated_coins < premine && !(current_block_weight >= 2 * full_reward_zone)) {
103  reward = premine;
104  return true;
105  }
106 
107  uint64_t base_reward;
108 
109  // After v9 the reward drops by ~75%, fixed reward curve that halves every 4 years (up to 2 halvings)
110  if(version >= 9) {
111 
112  uint64_t V9_BLOCK_HEIGHT = 0;
113  switch(nettype) {
114  case MAINNET:
115  V9_BLOCK_HEIGHT = 862866;
116  break;
117  case TESTNET:
118  V9_BLOCK_HEIGHT = 707121;
119  break;
120  case STAGENET:
121  V9_BLOCK_HEIGHT = 39000;
122  break;
123  default:
124  V9_BLOCK_HEIGHT = 39000;
125  }
126 
127  base_reward = version >= 10 ? 100 * COIN : 400 * COIN;
128  uint8_t halvings = (current_block_height - V9_BLOCK_HEIGHT) / 1051200; // Every 4 years
129 
130  // Tail emission after 2nd halving
131  if (halvings > 2) {
132 
133  //Force 2x tail emission after 2nd halving if circulating supply < max supply
134  base_reward = (already_generated_coins >= ETN_SUPPLY) ? FINAL_SUBSIDY_PER_MINUTE : FINAL_SUBSIDY_PER_MINUTE * 2;
135 
136  } else {
137  base_reward >>= halvings;
138  }
139  } else {
140  //After v8 the reward drops by ~75%
141  double emission_speed_factor = (version == 8 ? EMISSION_SPEED_FACTOR_PER_MINUTE_V8 : EMISSION_SPEED_FACTOR_PER_MINUTE) - (target_minutes-1);
142 
143  base_reward = (ETN_SUPPLY - already_generated_coins) / pow(2, emission_speed_factor);
144 
145  if (base_reward < FINAL_SUBSIDY_PER_MINUTE*target_minutes)
146  {
147  base_reward = FINAL_SUBSIDY_PER_MINUTE*target_minutes;
148  }
149  }
150 
151  //make it soft
152  if (median_weight < full_reward_zone) {
153  median_weight = full_reward_zone;
154  }
155 
156  if (current_block_weight <= median_weight) {
157  reward = base_reward;
158  return true;
159  }
160 
161  if(current_block_weight > 2 * median_weight) {
162  MERROR("Block cumulative weight is too big: " << current_block_weight << ", expected less than " << 2 * median_weight);
163  return false;
164  }
165 
166  assert(median_weight < std::numeric_limits<uint32_t>::max());
167  assert(current_block_weight < std::numeric_limits<uint32_t>::max());
168 
169  uint64_t product_hi;
170  // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being
171  // treated as 32-bit by default.
172  uint64_t multiplicand = 2 * median_weight - current_block_weight;
173  multiplicand *= current_block_weight;
174  uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi);
175 
176  uint64_t reward_hi;
177  uint64_t reward_lo;
178  div128_32(product_hi, product_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo);
179  div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo);
180  assert(0 == reward_hi);
181  assert(reward_lo < base_reward);
182 
183  reward = reward_lo;
184  return true;
185  }
186  //------------------------------------------------------------------------------------
188  {
189  const unsigned char* pbuf = reinterpret_cast<const unsigned char*>(&bl);
190  uint8_t summ = 0;
191  for(size_t i = 0; i!= sizeof(public_address_outer_blob)-1; i++)
192  summ += pbuf[i];
193 
194  return summ;
195  }
196  //------------------------------------------------------------------------------------
198  {
199  const unsigned char* pbuf = reinterpret_cast<const unsigned char*>(&bl);
200  uint8_t summ = 0;
201  for(size_t i = 0; i!= sizeof(public_integrated_address_outer_blob)-1; i++)
202  summ += pbuf[i];
203 
204  return summ;
205  }
206  //-----------------------------------------------------------------------
208  network_type nettype
209  , bool subaddress
210  , account_public_address const & adr
211  )
212  {
214 
215  return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr));
216  }
217  //-----------------------------------------------------------------------
219  network_type nettype
220  , account_public_address const & adr
221  , crypto::hash8 const & payment_id
222  )
223  {
224  uint64_t integrated_address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
225 
226  integrated_address iadr = {
227  adr, payment_id
228  };
229  return tools::base58::encode_addr(integrated_address_prefix, t_serializable_object_to_blob(iadr));
230  }
231  //-----------------------------------------------------------------------
232  bool is_coinbase(const transaction& tx)
233  {
234  if(tx.vin.size() != 1)
235  return false;
236 
237  if(tx.vin[0].type() != typeid(txin_gen))
238  return false;
239 
240  return true;
241  }
242  //-----------------------------------------------------------------------
245  , network_type nettype
246  , std::string const & str
247  )
248  {
250  uint64_t integrated_address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
252 
253  if (2 * sizeof(public_address_outer_blob) != str.size())
254  {
255  blobdata data;
256  uint64_t prefix;
257  if (!tools::base58::decode_addr(str, prefix, data))
258  {
259  LOG_PRINT_L2("Invalid address format");
260  return false;
261  }
262 
263  if (integrated_address_prefix == prefix)
264  {
265  info.is_subaddress = false;
266  info.has_payment_id = true;
267  }
268  else if (address_prefix == prefix)
269  {
270  info.is_subaddress = false;
271  info.has_payment_id = false;
272  }
273  else if (subaddress_prefix == prefix)
274  {
275  info.is_subaddress = true;
276  info.has_payment_id = false;
277  }
278  else {
279  LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << address_prefix
280  << " or " << integrated_address_prefix
281  << " or " << subaddress_prefix);
282  return false;
283  }
284 
285  if (info.has_payment_id)
286  {
287  integrated_address iadr;
288  if (!::serialization::parse_binary(data, iadr))
289  {
290  LOG_PRINT_L1("Account public address keys can't be parsed");
291  return false;
292  }
293  info.address = iadr.adr;
294  info.payment_id = iadr.payment_id;
295  }
296  else
297  {
298  if (!::serialization::parse_binary(data, info.address))
299  {
300  LOG_PRINT_L1("Account public address keys can't be parsed");
301  return false;
302  }
303  }
304 
305  if (!crypto::check_key(info.address.m_spend_public_key) || !crypto::check_key(info.address.m_view_public_key))
306  {
307  LOG_PRINT_L1("Failed to validate address keys");
308  return false;
309  }
310  }
311  else
312  {
313  // Old address format
314  std::string buff;
316  return false;
317 
318  if(buff.size()!=sizeof(public_address_outer_blob))
319  {
320  LOG_PRINT_L1("Wrong public address size: " << buff.size() << ", expected size: " << sizeof(public_address_outer_blob));
321  return false;
322  }
323 
324  public_address_outer_blob blob = *reinterpret_cast<const public_address_outer_blob*>(buff.data());
325 
326 
328  {
329  LOG_PRINT_L1("Unknown version of public address: " << blob.m_ver << ", expected " << CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER);
330  return false;
331  }
332 
333  if(blob.check_sum != get_account_address_checksum(blob))
334  {
335  LOG_PRINT_L1("Wrong public address checksum");
336  return false;
337  }
338 
339  //we success
340  info.address = blob.m_address;
341  info.is_subaddress = false;
342  info.has_payment_id = false;
343  }
344 
345  return true;
346  }
347  //--------------------------------------------------------------------------------
350  , network_type nettype
351  , const std::string& str_or_url
352  , std::function<std::string(const std::string&, const std::vector<std::string>&, bool)> dns_confirm
353  )
354  {
355  if (get_account_address_from_str(info, nettype, str_or_url))
356  return true;
357  bool dnssec_valid;
358  std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, dns_confirm);
359  return !address_str.empty() &&
360  get_account_address_from_str(info, nettype, address_str);
361  }
362  //--------------------------------------------------------------------------------
365  }
366 
369  }
370 }
371 
372 //--------------------------------------------------------------------------------
374 {
377  if (!res || buf.size() != sizeof(crypto::hash))
378  {
379  MERROR("invalid hash format: " << str_hash);
380  return false;
381  }
382  else
383  {
384  buf.copy(reinterpret_cast<char *>(&hash), sizeof(crypto::hash));
385  return true;
386  }
387 }
const char * res
Definition: hmac_keccak.cpp:41
#define EMISSION_SPEED_FACTOR_PER_MINUTE_V8
#define MERROR(x)
Definition: misc_log_ex.h:73
const config_t & get_config(network_type nettype)
bool is_coinbase(const transaction &tx)
#define EMISSION_SPEED_FACTOR_PER_MINUTE
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX
::std::string string
Definition: gtest-port.h:1097
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2
size_t get_min_block_weight(uint8_t version)
uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob &bl)
#define COIN
bool parse_binary(const std::string &blob, T &v)
Definition: binary_utils.h:41
unsigned char uint8_t
Definition: stdint.h:124
#define KV_SERIALIZE(varialble)
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V8
#define ETN_SUPPLY
std::string get_account_address_as_str_from_url(const std::string &url, bool &dnssec_valid, std::function< std::string(const std::string &, const std::vector< std::string > &, bool)> dns_confirm)
Definition: dns_utils.cpp:479
bool get_account_address_from_str_or_url(address_parse_info &info, network_type nettype, const std::string &str_or_url, std::function< std::string(const std::string &, const std::vector< std::string > &, bool)> dns_confirm)
#define END_SERIALIZE()
self-explanatory
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
#define CRYPTONOTE_MAX_TX_SIZE
#define DIFFICULTY_TARGET_V6
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER
std::string get_account_integrated_address_as_str(network_type nettype, account_public_address const &adr, crypto::hash8 const &payment_id)
bool get_block_hash(const block &b, crypto::hash &res)
uint8_t get_account_address_checksum(const public_address_outer_blob &bl)
unsigned __int64 uint64_t
Definition: stdint.h:136
#define BEGIN_SERIALIZE_OBJECT()
begins the environment of the DSL for described the serialization of an object
std::string encode_addr(uint64_t tag, const std::string &data)
Definition: base58.cpp:228
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V10
const char * buf
Definition: slow_memmem.cpp:74
version
Supported socks variants.
Definition: socks.h:57
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
std::string blobdata
Definition: blobdatatype.h:39
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
POD_CLASS hash8
Definition: hash.h:53
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX
#define FINAL_SUBSIDY_PER_MINUTE
crypto::hash get_transaction_hash(const transaction &t)
bool check_key(const public_key &key)
Definition: crypto.h:256
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
#define DIFFICULTY_TARGET
bool decode_addr(const std::string &addr, uint64_t &tag, std::string &data)
Definition: base58.cpp:238
POD_CLASS hash
Definition: hash.h:50
bool parse_hash256(const std::string &str_hash, crypto::hash &hash)
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 END_KV_SERIALIZE_MAP()
#define FIELD(f)
tags the field with the variable name and then serializes it
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5
#define BEGIN_KV_SERIALIZE_MAP()
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1
bool operator==(const cryptonote::block &a, const cryptonote::block &b)