Electroneum
Loading...
Searching...
No Matches
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>
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
55namespace cryptonote
56{
57 typedef std::vector<crypto::signature> ring_signature;
58
67
73
100
101 /* outputs */
102
104 {
105 std::vector<crypto::public_key> keys;
106 std::vector<uint8_t> script;
107
109 FIELD(keys)
112 };
113
118
125
127 {
130
131 std::string etn_address;
132
134
135 if (std::is_same<Archive<W>, json_archive<W>>())
136 {
137 std::stringstream ss;
140 std::string address_blob = ss.str();
141
142 if(!r) return false;
143
145
146 ar.tag("address");
147 ar.serialize_string(etn_address);
148 if (!ar.stream().good())
149 return false;
150
151 } else {
152 VARINT_FIELD(m_address_prefix)
154 }
156 };
157
158 /* inputs */
159
160 struct txin_gen
161 {
162 size_t height;
163
167 };
168
170 {
172 size_t prevout;
173 std::vector<uint8_t> sigset;
174
176 FIELD(prev)
180 };
181
196
198 {
200 std::vector<uint64_t> key_offsets;
201 crypto::key_image k_image; // double spending protection
202
208 };
209
222
224
226
227 //typedef std::pair<uint64_t, txout> out_t;
228
240
241 template<typename T> static inline unsigned int getpos(T &ar) { return 0; }
242 template<> inline unsigned int getpos(binary_archive<true> &ar) { return ar.stream().tellp(); }
243 template<> inline unsigned int getpos(binary_archive<false> &ar) { return ar.stream().tellg(); }
244
254
256 {
257
258 public:
259 // tx information
260 size_t version;
261 uint64_t unlock_time; //number of block (or time), used as a limitation like: spend this tx not early then block/time
262
263 std::vector<txin_v> vin;
264
265 std::vector<tx_out> vout;
266 //extra
267 std::vector<uint8_t> extra;
268
273 FIELD(vin)
274 FIELD(vout)
275 FIELD(extra)
277
278 public:
280 void set_null()
281 {
282 version = 1;
283 unlock_time = 0;
284 vin.clear();
285 vout.clear();
286 extra.clear();
287 }
289 {
290 unlock_time = 0;
291 vin.clear();
292 vout.clear();
293 extra.clear();
294 }
295 };
296
298 {
299 private:
300 // hash cash
301 mutable std::atomic<bool> hash_valid;
302 mutable std::atomic<bool> blob_size_valid;
303
304 public:
305 std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
307
308 // hash cash
310 mutable size_t blob_size;
311
312 bool pruned;
313
314 std::atomic<unsigned int> unprunable_size;
315 std::atomic<unsigned int> prefix_size;
316
317 transaction();
318 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); } }
319 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; }
320 virtual ~transaction();
321 void set_null();
322 void invalidate_hashes();
323 bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); }
324 void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); }
325 bool is_blob_size_valid() const { return blob_size_valid.load(std::memory_order_acquire); }
326 void set_blob_size_valid(bool v) const { blob_size_valid.store(v,std::memory_order_release); }
327 void set_hash(const crypto::hash &h) { hash = h; set_hash_valid(true); }
328 void set_blob_size(size_t sz) { blob_size = sz; set_blob_size_valid(true); }
329
331 if (!typename Archive<W>::is_saving())
332 {
333 set_hash_valid(false);
334 set_blob_size_valid(false);
335 }
336
337 const unsigned int start_pos = getpos(ar);
338
339 FIELDS(*static_cast<transaction_prefix *>(this))
340
341 if (std::is_same<Archive<W>, binary_archive<W>>())
342 {
343 prefix_size = getpos(ar) - start_pos;
344 unprunable_size = getpos(ar) - start_pos;
345 }
346
347 ar.tag("signatures");
348 ar.begin_array();
351 if (!signatures_not_expected && vin.size() != signatures.size())
352 return false;
353
354 if (!pruned) for (size_t i = 0; i < vin.size(); ++i)
355 {
356 size_t signature_size = get_signature_size(vin[i]);
358 {
359 if (0 == signature_size)
360 continue;
361 else
362 return false;
363 }
364
366 if (signature_size != signatures[i].size())
367 return false;
368
369 FIELDS(signatures[i]);
370
371 if (vin.size() - i > 1)
372 ar.delimit_array();
373 }
374 ar.end_array();
375
376 if (!typename Archive<W>::is_saving())
377 pruned = false;
379
380 template<bool W, template <bool> class Archive>
381 bool serialize_base(Archive<W> &ar)
382 {
383 FIELDS(*static_cast<transaction_prefix *>(this))
384
385 if (!typename Archive<W>::is_saving())
386 pruned = true;
387 return ar.stream().good();
388 }
389
390 private:
391 static size_t get_signature_size(const txin_v& tx_in);
392 };
393
394
395 inline
397 {
398 set_null();
399 }
400
401 inline
405
406 inline
408 {
410 signatures.clear();
412 set_hash_valid(false);
413 set_blob_size_valid(false);
414 pruned = false;
415 unprunable_size = 0;
416 prefix_size = 0;
417 }
418
419 inline
421 {
422 set_hash_valid(false);
423 set_blob_size_valid(false);
424 }
425
426 inline
427 size_t transaction::get_signature_size(const txin_v& tx_in)
428 {
429 struct txin_signature_size_visitor : public boost::static_visitor<size_t>
430 {
431 size_t operator()(const txin_gen& txin) const{return 0;}
432 size_t operator()(const txin_to_script& txin) const{return 0;}
433 size_t operator()(const txin_to_scripthash& txin) const{return 0;}
434 size_t operator()(const txin_to_key& txin) const {return txin.key_offsets.size();}
435 size_t operator()(const txin_to_key_public& txin) const {return 1;}
436 };
437
438 return boost::apply_visitor(txin_signature_size_visitor(), tx_in);
439 }
440
441
442
443 /************************************************************************/
444 /* */
445 /************************************************************************/
447 {
449 uint8_t minor_version; // now used as a voting mechanism, rather than how this particular block is built
453
459 FIELD(nonce)
461 };
462
463 struct block: public block_header
464 {
465 private:
466 // hash cash
467 mutable std::atomic<bool> hash_valid;
468
469 public:
470 block(): block_header(), hash_valid(false) {}
471 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); } }
472 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; }
474 bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); }
475 void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); }
476
478 std::vector<crypto::hash> tx_hashes;
479
480 mutable std::vector<uint8_t> signature;
481 mutable std::vector<uint8_t> signatory;
482
483 // hash cash
485
487 if (!typename Archive<W>::is_saving())
489
490 FIELDS(*static_cast<block_header *>(this))
495
497 return false;
498
500 };
501
502
503 /************************************************************************/
504 /* */
505 /************************************************************************/
506
507
508 struct keypair
509 {
512
513 static inline keypair generate(hw::device &hwdev)
514 {
515 keypair k;
516 hwdev.generate_keys(k.pub, k.sec);
517 return k;
518 }
519 };
520 //---------------------------------------------------------------
521
522}
523
524namespace std {
525 template <>
526 struct hash<cryptonote::account_public_address>
527 {
528 std::size_t operator()(const cryptonote::account_public_address& addr) const
529 {
530 // https://stackoverflow.com/a/17017281
531 size_t res = 17;
532 res = res * 31 + hash<crypto::public_key>()(addr.m_spend_public_key);
533 res = res * 31 + hash<crypto::public_key>()(addr.m_view_public_key);
534 return res;
535 }
536 };
537}
538
541
553
565
else if(0==res)
if(version==0||CURRENT_TRANSACTION_VERSION< version) return false
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
if(!typename Archive< W >::is_saving())
transaction(const transaction &t)
PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures)
transaction & operator=(const transaction &t)
std::vector< std::vector< crypto::signature > > signatures
void set_blob_size_valid(bool v) const
const unsigned int start_pos
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
#define CRYPTONOTE_MAX_TX_PER_BLOCK
#define CURRENT_TRANSACTION_VERSION
const char * res
#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()
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
POD_CLASS public_key
Definition crypto.h:79
POD_CLASS key_image
Definition crypto.h:105
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
@ RCTTypeNull
Definition rctTypes.h:229
bool serialize(Archive &ar, T &v)
STL namespace.
std::string encode_addr(uint64_t tag, const std::string &data)
Definition base58.cpp:228
#define BEGIN_SERIALIZE()
#define BEGIN_SERIALIZE_OBJECT()
#define BLOB_SERIALIZER(T)
#define true
#define FIELD(f)
#define false
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec)
#define FIELDS(f)
#define END_SERIALIZE()
#define VARIANT_TAG(Archive, Type, Tag)
#define VARINT_FIELD(f)
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
bool operator!=(const account_public_address &rhs) const
std::vector< uint8_t > signature
block & operator=(const block &b)
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
if(!typename Archive< W >::is_saving()) set_hash_valid(false)
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
if(std::is_same< Archive< W >, json_archive< W > >())
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
std::size_t operator()(const cryptonote::account_public_address &addr) const
const char * address
Definition multisig.cpp:37
for dealing with variants
#define T(x)