Electroneum
cryptonote_basic.h
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 #pragma once
33 
34 #include <boost/variant.hpp>
35 #include <boost/functional/hash/hash.hpp>
36 #include <vector>
37 #include <cstring> // memcmp
38 #include <sstream>
39 #include <atomic>
40 #include "serialization/variant.h"
41 #include "serialization/vector.h"
45 #include "serialization/crypto.h"
46 #include "serialization/keyvalue_serialization.h" // eepe named serialization
47 #include "cryptonote_config.h"
48 #include "crypto/crypto.h"
49 #include "crypto/hash.h"
50 #include "misc_language.h"
51 #include "ringct/rctTypes.h"
52 #include "device/device.hpp"
53 #include "common/base58.h"
54 
55 namespace cryptonote
56 {
57  typedef std::vector<crypto::signature> ring_signature;
58 
60  {
65  bool spent;
66  };
67 
69  {
72 
77 
82 
83  bool operator==(const account_public_address& rhs) const
84  {
85  return m_spend_public_key == rhs.m_spend_public_key &&
86  m_view_public_key == rhs.m_view_public_key;
87  }
88 
89  bool operator!=(const account_public_address& rhs) const
90  {
91  return !(*this == rhs);
92  }
93  };
94 
95  /* outputs */
96 
98  {
99  std::vector<crypto::public_key> keys;
100  std::vector<uint8_t> script;
101 
103  FIELD(keys)
104  FIELD(script)
105  END_SERIALIZE()
106  };
107 
109  {
111  };
112 
114  {
116  txout_to_key(const crypto::public_key &_key) : key(_key) { }
118  };
119 
121  {
124 
126 
128 
129  if (std::is_same<Archive<W>, json_archive<W>>())
130  {
131  std::stringstream ss;
132  binary_archive<true> ba(ss);
133  bool r = ::serialization::serialize(ba, const_cast<account_public_address&>(address));
134  std::string address_blob = ss.str();
135 
136  if(!r) return false;
137 
138  etn_address = tools::base58::encode_addr(m_address_prefix, address_blob);
139 
140  ar.tag("address");
141  ar.serialize_string(etn_address);
142  if (!ar.stream().good())
143  return false;
144 
145  } else {
146  VARINT_FIELD(m_address_prefix)
147  FIELD(address)
148  }
149  END_SERIALIZE()
150  };
151 
152  /* inputs */
153 
154  struct txin_gen
155  {
156  size_t height;
157 
160  END_SERIALIZE()
161  };
162 
164  {
166  size_t prevout;
167  std::vector<uint8_t> sigset;
168 
170  FIELD(prev)
171  VARINT_FIELD(prevout)
172  FIELD(sigset)
173  END_SERIALIZE()
174  };
175 
177  {
179  size_t prevout;
181  std::vector<uint8_t> sigset;
182 
184  FIELD(prev)
185  VARINT_FIELD(prevout)
186  FIELD(script)
187  FIELD(sigset)
188  END_SERIALIZE()
189  };
190 
191  struct txin_to_key
192  {
194  std::vector<uint64_t> key_offsets;
195  crypto::key_image k_image; // double spending protection
196 
198  VARINT_FIELD(amount)
199  FIELD(key_offsets)
200  FIELD(k_image)
201  END_SERIALIZE()
202  };
203 
205 {
209 
211  VARINT_FIELD(amount)
212  VARINT_FIELD(relative_offset)
213  FIELD(tx_hash)
214  END_SERIALIZE()
215 };
216 
218 
220 
221  //typedef std::pair<uint64_t, txout> out_t;
222 
223  struct tx_out
224  {
227 
229  VARINT_FIELD(amount)
230  FIELD(target)
231  END_SERIALIZE()
232 
233  };
234 
235  template<typename T> static inline unsigned int getpos(T &ar) { return 0; }
236  template<> inline unsigned int getpos(binary_archive<true> &ar) { return ar.stream().tellp(); }
237  template<> inline unsigned int getpos(binary_archive<false> &ar) { return ar.stream().tellg(); }
238 
239  struct validator_db {
241  std::vector<uint8_t> validators;
242 
244  VARINT_FIELD(expiration_date)
245  FIELD(validators)
246  END_SERIALIZE()
247  };
248 
250  {
251 
252  public:
253  // tx information
254  size_t version;
255  uint64_t unlock_time; //number of block (or time), used as a limitation like: spend this tx not early then block/time
256 
257  std::vector<txin_v> vin;
258 
259  std::vector<tx_out> vout;
260  //extra
261  std::vector<uint8_t> extra;
262 
266  VARINT_FIELD(unlock_time)
267  FIELD(vin)
268  FIELD(vout)
269  FIELD(extra)
270  END_SERIALIZE()
271 
272  public:
273  transaction_prefix(){ set_null(); }
274  void set_null()
275  {
276  version = 1;
277  unlock_time = 0;
278  vin.clear();
279  vout.clear();
280  extra.clear();
281  }
283  {
284  unlock_time = 0;
285  vin.clear();
286  vout.clear();
287  extra.clear();
288  }
289  };
290 
292  {
293  private:
294  // hash cash
295  mutable std::atomic<bool> hash_valid;
296  mutable std::atomic<bool> blob_size_valid;
297 
298  public:
299  std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
301 
302  // hash cash
304  mutable size_t blob_size;
305 
306  bool pruned;
307 
308  std::atomic<unsigned int> unprunable_size;
309  std::atomic<unsigned int> prefix_size;
310 
311  transaction();
312  transaction(const transaction &t): transaction_prefix(t), hash_valid(false), blob_size_valid(false), signatures(t.signatures), rct_signatures(t.rct_signatures), pruned(t.pruned), unprunable_size(t.unprunable_size.load()), prefix_size(t.prefix_size.load()) { if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } }
313  transaction &operator=(const transaction &t) { transaction_prefix::operator=(t); set_hash_valid(false); set_blob_size_valid(false); signatures = t.signatures; rct_signatures = t.rct_signatures; if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } pruned = t.pruned; unprunable_size = t.unprunable_size.load(); prefix_size = t.prefix_size.load(); return *this; }
314  virtual ~transaction();
315  void set_null();
316  void invalidate_hashes();
317  bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); }
318  void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); }
319  bool is_blob_size_valid() const { return blob_size_valid.load(std::memory_order_acquire); }
320  void set_blob_size_valid(bool v) const { blob_size_valid.store(v,std::memory_order_release); }
321  void set_hash(const crypto::hash &h) { hash = h; set_hash_valid(true); }
322  void set_blob_size(size_t sz) { blob_size = sz; set_blob_size_valid(true); }
323 
325  if (!typename Archive<W>::is_saving())
326  {
327  set_hash_valid(false);
328  set_blob_size_valid(false);
329  }
330 
331  const unsigned int start_pos = getpos(ar);
332 
333  FIELDS(*static_cast<transaction_prefix *>(this))
334 
335  if (std::is_same<Archive<W>, binary_archive<W>>())
336  {
337  prefix_size = getpos(ar) - start_pos;
338  unprunable_size = getpos(ar) - start_pos;
339  }
340 
341  ar.tag("signatures");
342  ar.begin_array();
343  PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures);
344  bool signatures_not_expected = signatures.empty();
345  if (!signatures_not_expected && vin.size() != signatures.size())
346  return false;
347 
348  if (!pruned) for (size_t i = 0; i < vin.size(); ++i)
349  {
350  size_t signature_size = get_signature_size(vin[i]);
351  if (signatures_not_expected)
352  {
353  if (0 == signature_size)
354  continue;
355  else
356  return false;
357  }
358 
359  PREPARE_CUSTOM_VECTOR_SERIALIZATION(signature_size, signatures[i]);
360  if (signature_size != signatures[i].size())
361  return false;
362 
363  FIELDS(signatures[i]);
364 
365  if (vin.size() - i > 1)
366  ar.delimit_array();
367  }
368  ar.end_array();
369 
370  if (!typename Archive<W>::is_saving())
371  pruned = false;
372  END_SERIALIZE()
373 
374  template<bool W, template <bool> class Archive>
375  bool serialize_base(Archive<W> &ar)
376  {
377  FIELDS(*static_cast<transaction_prefix *>(this))
378 
379  if (!typename Archive<W>::is_saving())
380  pruned = true;
381  return ar.stream().good();
382  }
383 
384  private:
385  static size_t get_signature_size(const txin_v& tx_in);
386  };
387 
388 
389  inline
391  {
392  set_null();
393  }
394 
395  inline
397  {
398  }
399 
400  inline
402  {
404  signatures.clear();
405  rct_signatures.type = rct::RCTTypeNull;
406  set_hash_valid(false);
407  set_blob_size_valid(false);
408  pruned = false;
409  unprunable_size = 0;
410  prefix_size = 0;
411  }
412 
413  inline
415  {
416  set_hash_valid(false);
417  set_blob_size_valid(false);
418  }
419 
420  inline
421  size_t transaction::get_signature_size(const txin_v& tx_in)
422  {
423  struct txin_signature_size_visitor : public boost::static_visitor<size_t>
424  {
425  size_t operator()(const txin_gen& txin) const{return 0;}
426  size_t operator()(const txin_to_script& txin) const{return 0;}
427  size_t operator()(const txin_to_scripthash& txin) const{return 0;}
428  size_t operator()(const txin_to_key& txin) const {return txin.key_offsets.size();}
429  size_t operator()(const txin_to_key_public& txin) const {return 1;}
430  };
431 
432  return boost::apply_visitor(txin_signature_size_visitor(), tx_in);
433  }
434 
435 
436 
437  /************************************************************************/
438  /* */
439  /************************************************************************/
441  {
443  uint8_t minor_version; // now used as a voting mechanism, rather than how this particular block is built
447 
449  VARINT_FIELD(major_version)
450  VARINT_FIELD(minor_version)
451  VARINT_FIELD(timestamp)
452  FIELD(prev_id)
453  FIELD(nonce)
454  END_SERIALIZE()
455  };
456 
457  struct block: public block_header
458  {
459  private:
460  // hash cash
461  mutable std::atomic<bool> hash_valid;
462 
463  public:
464  block(): block_header(), hash_valid(false) {}
465  block(const block &b): block_header(b), hash_valid(false), miner_tx(b.miner_tx), tx_hashes(b.tx_hashes), signature(b.signature), signatory(b.signatory) { if (b.is_hash_valid()) { hash = b.hash; set_hash_valid(true); } }
466  block &operator=(const block &b) { block_header::operator=(b); hash_valid = false; miner_tx = b.miner_tx; tx_hashes = b.tx_hashes; signature = b.signature; signatory = b.signatory; if (b.is_hash_valid()) { hash = b.hash; set_hash_valid(true); } return *this; }
467  void invalidate_hashes() { set_hash_valid(false); }
468  bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); }
469  void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); }
470 
472  std::vector<crypto::hash> tx_hashes;
473 
474  mutable std::vector<uint8_t> signature;
475  mutable std::vector<uint8_t> signatory;
476 
477  // hash cash
479 
481  if (!typename Archive<W>::is_saving())
482  set_hash_valid(false);
483 
484  FIELDS(*static_cast<block_header *>(this))
485  FIELD(miner_tx)
486  FIELD(tx_hashes)
488  FIELD(signatory)
489 
490  if (tx_hashes.size() > CRYPTONOTE_MAX_TX_PER_BLOCK)
491  return false;
492 
493  END_SERIALIZE()
494  };
495 
496 
497  /************************************************************************/
498  /* */
499  /************************************************************************/
500 
501 
502  struct keypair
503  {
506 
507  static inline keypair generate(hw::device &hwdev)
508  {
509  keypair k;
510  hwdev.generate_keys(k.pub, k.sec);
511  return k;
512  }
513  };
514  //---------------------------------------------------------------
515 
516 }
517 
518 namespace std {
519  template <>
520  struct hash<cryptonote::account_public_address>
521  {
522  std::size_t operator()(const cryptonote::account_public_address& addr) const
523  {
524  // https://stackoverflow.com/a/17017281
525  size_t res = 17;
526  res = res * 31 + hash<crypto::public_key>()(addr.m_spend_public_key);
527  res = res * 31 + hash<crypto::public_key>()(addr.m_view_public_key);
528  return res;
529  }
530  };
531 }
532 
535 
547 
559 
return true
else if(0==res)
connection< TProtocol > & operator=(const connection< TProtocol > &obj)
uint64_t height
Definition: blockchain.cpp:91
std::vector< uint8_t > extra
transaction & operator=(const transaction &t)
void set_hash(const crypto::hash &h)
std::atomic< unsigned int > unprunable_size
std::atomic< unsigned int > prefix_size
void set_blob_size(size_t sz)
void set_hash_valid(bool v) const
transaction(const transaction &t)
PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures)
std::vector< std::vector< crypto::signature > > signatures
void set_blob_size_valid(bool v) const
virtual crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key &recovery_key=crypto::secret_key(), bool recover=false)=0
VARIANT_TAG(binary_archive, cryptonote::txin_gen, 0xff)
BLOB_SERIALIZER(cryptonote::txout_to_key)
#define CRYPTONOTE_MAX_TX_PER_BLOCK
#define CURRENT_TRANSACTION_VERSION
const uint32_t T[512]
const char * res
Definition: hmac_keccak.cpp:41
const char * key
Definition: hmac_keccak.cpp:39
#define inline
Definition: inline_c.h:35
JSON archive.
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble)
#define END_KV_SERIALIZE_MAP()
#define BEGIN_KV_SERIALIZE_MAP()
void load(Archive &a, std::unordered_map< h_key, hval > &x, const boost::serialization::version_type ver)
POD_CLASS signature
Definition: crypto.h:108
POD_CLASS public_key
Definition: crypto.h:76
POD_CLASS key_image
Definition: crypto.h:102
POD_CLASS hash
Definition: hash.h:50
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
std::vector< crypto::signature > ring_signature
boost::variant< txout_to_script, txout_to_scripthash, txout_to_key, txout_to_key_public > txout_target_v
version
Supported socks variants.
Definition: socks.h:58
@ RCTTypeNull
Definition: rctTypes.h:229
::std::string string
Definition: gtest-port.h:1097
std::string encode_addr(uint64_t tag, const std::string &data)
Definition: base58.cpp:228
void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization::version_type ver)
#define BEGIN_SERIALIZE()
Begins the environment of the DSL \detailed for describing how to serialize an of an archive type.
#define BEGIN_SERIALIZE_OBJECT()
begins the environment of the DSL \detailed for described the serialization of an object
#define FIELD(f)
tags the field with the variable name and then serializes it
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec)
#define FIELDS(f)
does not add a tag to the serialized value
#define END_SERIALIZE()
self-explanatory
#define VARINT_FIELD(f)
tags and serializes the varint f
#define false
Definition: stdbool.h:38
unsigned int uint32_t
Definition: stdint.h:126
unsigned char uint8_t
Definition: stdint.h:124
unsigned __int64 uint64_t
Definition: stdint.h:136
stream_type & stream()
bool operator!=(const account_public_address &rhs) const
std::vector< uint8_t > signature
bool is_hash_valid() const
void set_hash_valid(bool v) const
std::vector< uint8_t > signatory
block(const block &b)
std::vector< crypto::hash > tx_hashes
block & operator=(const block &b)
crypto::secret_key sec
static keypair generate(hw::device &hwdev)
crypto::public_key pub
txout_target_v target
crypto::key_image k_image
std::vector< uint64_t > key_offsets
std::vector< uint8_t > sigset
std::vector< uint8_t > sigset
cryptonote::account_public_address address
crypto::public_key key
txout_to_key(const crypto::public_key &_key)
std::vector< crypto::public_key > keys
std::vector< uint8_t > script
std::vector< uint8_t > validators
a archive using the JSON standard
Definition: json_archive.h:112
uint8_t type
Definition: rctTypes.h:241
std::size_t operator()(const cryptonote::account_public_address &addr) const
const char * address
Definition: multisig.cpp:37
for dealing with variants