Electroneum
cryptonote_basic.h
Go to the documentation of this file.
1 // Copyrights(c) 2017-2019, The Electroneum Project
2 // Copyrights(c) 2014-2017, 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>
41 #include "serialization/variant.h"
42 #include "serialization/vector.h"
46 #include "serialization/crypto.h"
47 #include "serialization/keyvalue_serialization.h" // eepe named serialization
48 #include "cryptonote_config.h"
49 #include "crypto/crypto.h"
50 #include "crypto/hash.h"
51 #include "misc_language.h"
52 #include "tx_extra.h"
53 #include "ringct/rctTypes.h"
54 
55 namespace cryptonote
56 {
57 
58  const static crypto::hash null_hash = AUTO_VAL_INIT(null_hash);
59  const static crypto::hash8 null_hash8 = AUTO_VAL_INIT(null_hash8);
60  const static crypto::public_key null_pkey = AUTO_VAL_INIT(null_pkey);
61 
62  typedef std::vector<crypto::signature> ring_signature;
63 
64 
65  /* outputs */
66 
68  {
69  std::vector<crypto::public_key> keys;
70  std::vector<uint8_t> script;
71 
73  FIELD(keys)
74  FIELD(script)
76  };
77 
79  {
81  };
82 
83  struct txout_to_key
84  {
86  txout_to_key(const crypto::public_key &_key) : key(_key) { }
88  };
89 
90 
91  /* inputs */
92 
93  struct txin_gen
94  {
95  size_t height;
96 
100  };
101 
103  {
105  size_t prevout;
106  std::vector<uint8_t> sigset;
107 
109  FIELD(prev)
110  VARINT_FIELD(prevout)
111  FIELD(sigset)
112  END_SERIALIZE()
113  };
114 
116  {
118  size_t prevout;
120  std::vector<uint8_t> sigset;
121 
123  FIELD(prev)
124  VARINT_FIELD(prevout)
125  FIELD(script)
126  FIELD(sigset)
127  END_SERIALIZE()
128  };
129 
130  struct txin_to_key
131  {
132  uint64_t amount;
133  std::vector<uint64_t> key_offsets;
134  crypto::key_image k_image; // double spending protection
135 
137  VARINT_FIELD(amount)
138  FIELD(key_offsets)
139  FIELD(k_image)
140  END_SERIALIZE()
141  };
142 
143 
145 
147 
148  //typedef std::pair<uint64_t, txout> out_t;
149  struct tx_out
150  {
151  uint64_t amount;
153 
155  VARINT_FIELD(amount)
156  FIELD(target)
157  END_SERIALIZE()
158 
159 
160  };
161 
162  struct validator_db {
163  uint64_t expiration_date;
164  std::string validators;
165 
167  VARINT_FIELD(expiration_date)
168  FIELD(validators)
169  END_SERIALIZE()
170  };
171 
173  {
174 
175  public:
176  // tx information
177  size_t version;
178  uint64_t unlock_time; //number of block (or time), used as a limitation like: spend this tx not early then block/time
179 
180  std::vector<txin_v> vin;
181  std::vector<tx_out> vout;
182  //extra
183  std::vector<uint8_t> extra;
184 
187  if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false;
188  VARINT_FIELD(unlock_time)
189  FIELD(vin)
190  FIELD(vout)
191  FIELD(extra)
192  END_SERIALIZE()
193 
194  public:
196  };
197 
199  {
200  private:
201  // hash cash
202  mutable std::atomic<bool> hash_valid;
203  mutable std::atomic<bool> blob_size_valid;
204 
205  public:
206  std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
208 
209  // hash cash
211  mutable size_t blob_size;
212 
213  transaction();
214  transaction(const transaction &t): transaction_prefix(t), hash_valid(false), 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); } }
215  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); } return *this; }
216  virtual ~transaction();
217  void set_null();
218  void invalidate_hashes();
219  bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); }
220  void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); }
221  bool is_blob_size_valid() const { return blob_size_valid.load(std::memory_order_acquire); }
222  void set_blob_size_valid(bool v) const { blob_size_valid.store(v,std::memory_order_release); }
223 
225  if (!typename Archive<W>::is_saving())
226  {
227  set_hash_valid(false);
228  set_blob_size_valid(false);
229  }
230 
231  FIELDS(*static_cast<transaction_prefix *>(this))
232 
233  if (version == 1)
234  {
235  ar.tag("signatures");
236  ar.begin_array();
237  PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures);
238  bool signatures_not_expected = signatures.empty();
239  if (!signatures_not_expected && vin.size() != signatures.size())
240  return false;
241 
242  for (size_t i = 0; i < vin.size(); ++i)
243  {
244  size_t signature_size = get_signature_size(vin[i]);
245  if (signatures_not_expected)
246  {
247  if (0 == signature_size)
248  continue;
249  else
250  return false;
251  }
252 
253  PREPARE_CUSTOM_VECTOR_SERIALIZATION(signature_size, signatures[i]);
254  if (signature_size != signatures[i].size())
255  return false;
256 
257  FIELDS(signatures[i]);
258 
259  if (vin.size() - i > 1)
260  ar.delimit_array();
261  }
262  ar.end_array();
263  }
264  else
265  {
266  ar.tag("rct_signatures");
267  if (!vin.empty())
268  {
269  ar.begin_object();
270  bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size());
271  if (!r || !ar.stream().good()) return false;
272  ar.end_object();
273  if (rct_signatures.type != rct::RCTTypeNull)
274  {
275  ar.tag("rctsig_prunable");
276  ar.begin_object();
277  r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(),
278  vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0);
279  if (!r || !ar.stream().good()) return false;
280  ar.end_object();
281  }
282  }
283  }
284  END_SERIALIZE()
285 
286  template<bool W, template <bool> class Archive>
287  bool serialize_base(Archive<W> &ar)
288  {
289  FIELDS(*static_cast<transaction_prefix *>(this))
290 
291  if (version == 1)
292  {
293  }
294  else
295  {
296  ar.tag("rct_signatures");
297  if (!vin.empty())
298  {
299  ar.begin_object();
300  bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size());
301  if (!r || !ar.stream().good()) return false;
302  ar.end_object();
303  }
304  }
305  return ar.stream().good();
306  }
307 
308  private:
309  static size_t get_signature_size(const txin_v& tx_in);
310  };
311 
312 
313  inline
315  {
316  set_null();
317  }
318 
319  inline
321  {
322  //set_null();
323  }
324 
325  inline
327  {
328  version = 1;
329  unlock_time = 0;
330  vin.clear();
331  vout.clear();
332  extra.clear();
333  signatures.clear();
334  rct_signatures.type = rct::RCTTypeNull;
335  set_hash_valid(false);
336  set_blob_size_valid(false);
337  }
338 
339  inline
341  {
342  set_hash_valid(false);
343  set_blob_size_valid(false);
344  }
345 
346  inline
348  {
349  struct txin_signature_size_visitor : public boost::static_visitor<size_t>
350  {
351  size_t operator()(const txin_gen& txin) const{return 0;}
352  size_t operator()(const txin_to_script& txin) const{return 0;}
353  size_t operator()(const txin_to_scripthash& txin) const{return 0;}
354  size_t operator()(const txin_to_key& txin) const {return txin.key_offsets.size();}
355  };
356 
357  return boost::apply_visitor(txin_signature_size_visitor(), tx_in);
358  }
359 
360 
361 
362  /************************************************************************/
363  /* */
364  /************************************************************************/
366  {
367  uint8_t major_version;
368  uint8_t minor_version; // now used as a voting mechanism, rather than how this particular block is built
369  uint64_t timestamp;
371  uint32_t nonce;
372 
374  VARINT_FIELD(major_version)
375  VARINT_FIELD(minor_version)
376  VARINT_FIELD(timestamp)
377  FIELD(prev_id)
378  FIELD(nonce)
379  END_SERIALIZE()
380  };
381 
382  struct block: public block_header
383  {
384  private:
385  // hash cash
386  mutable std::atomic<bool> hash_valid;
387 
388  public:
389  block(): block_header(), hash_valid(false) {}
390  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); } }
391  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; }
392  void invalidate_hashes() { set_hash_valid(false); }
393  bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); }
394  void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); }
395 
397  std::vector<crypto::hash> tx_hashes;
398 
399  std::string signature;
400  mutable std::string signatory;
401 
402  // hash cash
404 
406  if (!typename Archive<W>::is_saving())
407  set_hash_valid(false);
408 
409  FIELDS(*static_cast<block_header *>(this))
410  FIELD(miner_tx)
411  FIELD(tx_hashes)
413  FIELD(signatory)
414  END_SERIALIZE()
415  };
416 
417 
418  /************************************************************************/
419  /* */
420  /************************************************************************/
422  {
425 
427  FIELD(m_spend_public_key)
428  FIELD(m_view_public_key)
429  END_SERIALIZE()
430 
431  BEGIN_KV_SERIALIZE_MAP()
432  KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_public_key)
433  KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_public_key)
434  END_KV_SERIALIZE_MAP()
435  };
436 
437  struct keypair
438  {
441 
442  static inline keypair generate()
443  {
444  keypair k;
445  generate_keys(k.pub, k.sec);
446  return k;
447  }
448  };
449  //---------------------------------------------------------------
450 
451 }
452 
455 
465 
475 
crypto::public_key pub
Definition: cryptonote_basic.h:439
block & operator=(const block &b)
Definition: cryptonote_basic.h:391
std::vector< crypto::hash > tx_hashes
Definition: cryptonote_basic.h:397
uint8_t minor_version
Definition: cryptonote_basic.h:368
boost::variant< txout_to_script, txout_to_scripthash, txout_to_key > txout_target_v
Definition: cryptonote_basic.h:146
Definition: cryptonote_basic.h:115
static size_t get_signature_size(const txin_v &tx_in)
Definition: cryptonote_basic.h:347
transaction()
Definition: cryptonote_basic.h:314
txout_to_script script
Definition: cryptonote_basic.h:119
Definition: unordered_containers_boost_serialization.h:38
crypto::secret_key sec
Definition: cryptonote_basic.h:440
static const crypto::hash8 null_hash8
Definition: cryptonote_basic.h:59
Definition: cryptonote_basic.h:437
bool serialize_rctsig_prunable(Archive< W > &ar, uint8_t type, size_t inputs, size_t outputs, size_t mixin)
Definition: rctTypes.h:252
Definition: cryptonote_basic.h:382
virtual ~transaction()
Definition: cryptonote_basic.h:320
bool is_blob_size_valid() const
Definition: cryptonote_basic.h:221
Definition: cryptonote_basic.h:365
uint64_t height
Definition: blockchain.cpp:87
uint8_t major_version
Definition: cryptonote_basic.h:367
static keypair generate()
Definition: cryptonote_basic.h:442
size_t prevout
Definition: cryptonote_basic.h:118
Definition: rctTypes.h:177
static const crypto::hash null_hash
Definition: cryptonote_basic.h:58
size_t prevout
Definition: cryptonote_basic.h:105
transaction(const transaction &t)
Definition: cryptonote_basic.h:214
std::vector< uint64_t > key_offsets
Definition: cryptonote_basic.h:133
Definition: cryptonote_basic.h:83
Definition: cryptonote_basic.h:67
Definition: cryptonote_basic.h:93
std::vector< crypto::signature > ring_signature
Definition: cryptonote_basic.h:62
std::vector< uint8_t > extra
Definition: cryptonote_basic.h:183
crypto::hash prev
Definition: cryptonote_basic.h:104
#define END_SERIALIZE()
self-explanatory
Definition: serialization.h:207
Definition: cryptonote_basic.h:172
std::vector< tx_out > vout
Definition: cryptonote_basic.h:181
Holds cryptonote related classes and helpers.
Definition: db_bdb.cpp:225
bool is_hash_valid() const
Definition: cryptonote_basic.h:393
Definition: cryptonote_basic.h:162
Definition: cryptonote_basic.h:102
Simple DSL AAPI based on.
std::vector< txin_v > vin
Definition: cryptonote_basic.h:180
crypto::public_key m_spend_public_key
Definition: cryptonote_basic.h:423
std::vector< uint8_t > script
Definition: cryptonote_basic.h:70
for dealing with variants
block()
Definition: cryptonote_basic.h:389
Definition: cryptonote_basic.h:78
uint64_t unlock_time
Definition: cryptonote_basic.h:178
void invalidate_hashes()
Definition: cryptonote_basic.h:392
crypto::public_key m_view_public_key
Definition: cryptonote_basic.h:424
void set_blob_size_valid(bool v) const
Definition: cryptonote_basic.h:222
rct::rctSig rct_signatures
Definition: cryptonote_basic.h:207
std::atomic< bool > hash_valid
Definition: cryptonote_basic.h:386
void set_hash_valid(bool v) const
Definition: cryptonote_basic.h:394
#define FIELDS(f)
does not add a tag to the serialized value
Definition: serialization.h:247
rctSigPrunable p
Definition: rctTypes.h:324
void invalidate_hashes()
Definition: cryptonote_basic.h:340
static const crypto::public_key null_pkey
Definition: cryptonote_basic.h:60
uint64_t amount
Definition: cryptonote_basic.h:132
int b
Definition: base.py:1
uint64_t timestamp
Definition: cryptonote_basic.h:369
Definition: cryptonote_basic.h:130
#define BEGIN_SERIALIZE_OBJECT()
begins the environment of the DSL for described the serialization of an object
Definition: serialization.h:188
secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.h:184
Definition: rctTypes.h:323
size_t version
Definition: cryptonote_basic.h:177
uint64_t expiration_date
Definition: cryptonote_basic.h:163
#define false
Definition: stdbool.h:38
std::atomic< bool > blob_size_valid
Definition: cryptonote_basic.h:203
transaction miner_tx
Definition: cryptonote_basic.h:396
crypto::hash hash
Definition: cryptonote_basic.h:80
POD_CLASS public_key
Definition: crypto.h:65
void set_null()
Definition: cryptonote_basic.h:326
std::string signature
Definition: cryptonote_basic.h:399
bool is_hash_valid() const
Definition: cryptonote_basic.h:219
BLOB_SERIALIZER(cryptonote::txout_to_key)
uint8_t version
Definition: blockchain.cpp:86
std::vector< std::vector< crypto::signature > > signatures
Definition: cryptonote_basic.h:206
std::vector< uint8_t > sigset
Definition: cryptonote_basic.h:106
POD_CLASS signature
Definition: crypto.h:99
Definition: cryptonote_basic.h:421
crypto::hash prev
Definition: cryptonote_basic.h:117
POD_CLASS hash8
Definition: hash.h:49
crypto::public_key key
Definition: cryptonote_basic.h:87
transaction & operator=(const transaction &t)
Definition: cryptonote_basic.h:215
std::string signatory
Definition: cryptonote_basic.h:400
std::string validators
Definition: cryptonote_basic.h:164
POD_CLASS key_image
Definition: crypto.h:93
#define VARINT_FIELD(f)
tags and serializes the varint f
Definition: serialization.h:256
POD_CLASS secret_key
Definition: crypto.h:69
VARIANT_TAG(binary_archive, cryptonote::txin_gen, 0xff)
std::vector< uint8_t > sigset
Definition: cryptonote_basic.h:120
uint64_t amount
Definition: cryptonote_basic.h:151
uint8_t type
Definition: rctTypes.h:182
txout_target_v target
Definition: cryptonote_basic.h:152
crypto::key_image k_image
Definition: cryptonote_basic.h:134
crypto::hash hash
Definition: cryptonote_basic.h:210
void set_hash_valid(bool v) const
Definition: cryptonote_basic.h:220
std::atomic< bool > hash_valid
Definition: cryptonote_basic.h:202
block(const block &b)
Definition: cryptonote_basic.h:390
txout_to_key()
Definition: cryptonote_basic.h:85
#define BEGIN_SERIALIZE()
Begins the environment of the DSL for describing how to serialize an of an archive type...
Definition: serialization.h:179
std::vector< crypto::public_key > keys
Definition: cryptonote_basic.h:69
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key > txin_v
Definition: cryptonote_basic.h:144
crypto::hash prev_id
Definition: cryptonote_basic.h:370
POD_CLASS hash
Definition: hash.h:46
JSON archive.
txout_to_key(const crypto::public_key &_key)
Definition: cryptonote_basic.h:86
#define CURRENT_TRANSACTION_VERSION
Definition: cryptonote_config.h:46
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec)
Definition: serialization.h:201
crypto::hash hash
Definition: cryptonote_basic.h:403
Definition: cryptonote_basic.h:149
bool serialize_rctsig_base(Archive< W > &ar, size_t inputs, size_t outputs)
Definition: rctTypes.h:192
#define FIELD(f)
tags the field with the variable name and then serializes it
Definition: serialization.h:236
size_t blob_size
Definition: cryptonote_basic.h:211
size_t height
Definition: cryptonote_basic.h:95
Definition: binary_archive.h:95
Definition: debug_archive.h:38
uint32_t nonce
Definition: cryptonote_basic.h:371
Definition: cryptonote_basic.h:198
a archive using the JSON standard
Definition: json_archive.h:112