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