Electroneum
cryptonote_format_utils.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 <atomic>
33 #include <boost/algorithm/string.hpp>
34 #include "wipeable_string.h"
35 #include "string_tools.h"
36 #include "serialization/string.h"
38 #include "cryptonote_config.h"
39 #include "crypto/crypto.h"
40 #include "crypto/hash.h"
41 #include "ringct/rctSigs.h"
42 
43 using namespace epee;
44 
45 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
46 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "cn"
47 
48 #define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
49 
50 // #define ENABLE_HASH_CASH_INTEGRITY_CHECK
51 
52 using namespace crypto;
53 
54 static const uint64_t valid_decomposed_outputs[] = {
55  (uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9,
56  (uint64_t)10, (uint64_t)20, (uint64_t)30, (uint64_t)40, (uint64_t)50, (uint64_t)60, (uint64_t)70, (uint64_t)80, (uint64_t)90,
57  (uint64_t)100, (uint64_t)200, (uint64_t)300, (uint64_t)400, (uint64_t)500, (uint64_t)600, (uint64_t)700, (uint64_t)800, (uint64_t)900, // 100 = 1 Electroneum
58  (uint64_t)1000, (uint64_t)2000, (uint64_t)3000, (uint64_t)4000, (uint64_t)5000, (uint64_t)6000, (uint64_t)7000, (uint64_t)8000, (uint64_t)9000,
59  (uint64_t)10000, (uint64_t)20000, (uint64_t)30000, (uint64_t)40000, (uint64_t)50000, (uint64_t)60000, (uint64_t)70000, (uint64_t)80000, (uint64_t)90000,
60  (uint64_t)100000, (uint64_t)200000, (uint64_t)300000, (uint64_t)400000, (uint64_t)500000, (uint64_t)600000, (uint64_t)700000, (uint64_t)800000, (uint64_t)900000,
61  (uint64_t)1000000, (uint64_t)2000000, (uint64_t)3000000, (uint64_t)4000000, (uint64_t)5000000, (uint64_t)6000000, (uint64_t)7000000, (uint64_t)8000000, (uint64_t)9000000,
62  (uint64_t)10000000, (uint64_t)20000000, (uint64_t)30000000, (uint64_t)40000000, (uint64_t)50000000, (uint64_t)60000000, (uint64_t)70000000, (uint64_t)80000000, (uint64_t)90000000,
63  (uint64_t)100000000, (uint64_t)200000000, (uint64_t)300000000, (uint64_t)400000000, (uint64_t)500000000, (uint64_t)600000000, (uint64_t)700000000, (uint64_t)800000000, (uint64_t)900000000,
64  (uint64_t)1000000000, (uint64_t)2000000000, (uint64_t)3000000000, (uint64_t)4000000000, (uint64_t)5000000000, (uint64_t)6000000000, (uint64_t)7000000000, (uint64_t)8000000000, (uint64_t)9000000000,
65  (uint64_t)10000000000, (uint64_t)20000000000, (uint64_t)30000000000, (uint64_t)40000000000, (uint64_t)50000000000, (uint64_t)60000000000, (uint64_t)70000000000, (uint64_t)80000000000, (uint64_t)90000000000,
66  (uint64_t)100000000000, (uint64_t)200000000000, (uint64_t)300000000000, (uint64_t)400000000000, (uint64_t)500000000000, (uint64_t)600000000000, (uint64_t)700000000000, (uint64_t)800000000000, (uint64_t)900000000000,
67  (uint64_t)1000000000000, (uint64_t)2000000000000, (uint64_t)3000000000000, (uint64_t)4000000000000, (uint64_t)5000000000000, (uint64_t)6000000000000, (uint64_t)7000000000000, (uint64_t)8000000000000, (uint64_t)9000000000000,
68  (uint64_t)10000000000000, (uint64_t)20000000000000, (uint64_t)30000000000000, (uint64_t)40000000000000, (uint64_t)50000000000000, (uint64_t)60000000000000, (uint64_t)70000000000000, (uint64_t)80000000000000, (uint64_t)90000000000000,
69  (uint64_t)100000000000000, (uint64_t)200000000000000, (uint64_t)300000000000000, (uint64_t)400000000000000, (uint64_t)500000000000000, (uint64_t)600000000000000, (uint64_t)700000000000000, (uint64_t)800000000000000, (uint64_t)900000000000000,
70  (uint64_t)1000000000000000, (uint64_t)2000000000000000, (uint64_t)3000000000000000, (uint64_t)4000000000000000, (uint64_t)5000000000000000, (uint64_t)6000000000000000, (uint64_t)7000000000000000, (uint64_t)8000000000000000, (uint64_t)9000000000000000,
71  (uint64_t)10000000000000000, (uint64_t)20000000000000000, (uint64_t)30000000000000000, (uint64_t)40000000000000000, (uint64_t)50000000000000000, (uint64_t)60000000000000000, (uint64_t)70000000000000000, (uint64_t)80000000000000000, (uint64_t)90000000000000000,
72  (uint64_t)100000000000000000, (uint64_t)200000000000000000, (uint64_t)300000000000000000, (uint64_t)400000000000000000, (uint64_t)500000000000000000, (uint64_t)600000000000000000, (uint64_t)700000000000000000, (uint64_t)800000000000000000, (uint64_t)900000000000000000,
73  (uint64_t)1000000000000000000, (uint64_t)2000000000000000000, (uint64_t)3000000000000000000, (uint64_t)4000000000000000000, (uint64_t)5000000000000000000, (uint64_t)6000000000000000000, (uint64_t)7000000000000000000, (uint64_t)8000000000000000000, (uint64_t)9000000000000000000,
74  (uint64_t)10000000000000000000ull
75 };
76 
77 static std::atomic<unsigned int> default_decimal_point(CRYPTONOTE_DISPLAY_DECIMAL_POINT);
78 
79 static std::atomic<uint64_t> tx_hashes_calculated_count(0);
80 static std::atomic<uint64_t> tx_hashes_cached_count(0);
81 static std::atomic<uint64_t> block_hashes_calculated_count(0);
82 static std::atomic<uint64_t> block_hashes_cached_count(0);
83 
84 #define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) {if(!(expr)) {MWARNING(message); throw std::runtime_error(message);}}
85 
86 namespace cryptonote
87 {
88  static inline unsigned char *operator &(ec_point &point) {
89  return &reinterpret_cast<unsigned char &>(point);
90  }
91  static inline const unsigned char *operator &(const ec_point &point) {
92  return &reinterpret_cast<const unsigned char &>(point);
93  }
94 
95  // a copy of rct::addKeys, since we can't link to libringct to avoid circular dependencies
96  static void add_public_key(crypto::public_key &AB, const crypto::public_key &A, const crypto::public_key &B) {
97  ge_p3 B2, A2;
98  CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&B2, &B) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
99  CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A2, &A) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
100  ge_cached tmp2;
101  ge_p3_to_cached(&tmp2, &B2);
102  ge_p1p1 tmp3;
103  ge_add(&tmp3, &A2, &tmp2);
104  ge_p1p1_to_p3(&A2, &tmp3);
105  ge_p3_tobytes(&AB, &A2);
106  }
107 }
108 
109 namespace cryptonote
110 {
111  //---------------------------------------------------------------
113  {
114  std::ostringstream s;
116  ::serialization::serialize(a, const_cast<transaction_prefix&>(tx));
117 
118  crypto::cn_fast_hash(s.str().data(), s.str().size(), h);
119  }
120  //---------------------------------------------------------------
122  {
123  crypto::hash h = null_hash;
125  return h;
126  }
127  //---------------------------------------------------------------
128  bool expand_transaction_1(transaction &tx, bool base_only)
129  {
130  return true;
131  }
132  //---------------------------------------------------------------
134  {
135  std::stringstream ss;
136  ss << tx_blob;
137  binary_archive<false> ba(ss);
138  bool r = ::serialization::serialize(ba, tx);
139  CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
140  CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
141  tx.invalidate_hashes();
142  tx.set_blob_size(tx_blob.size());
143  return true;
144  }
145  //---------------------------------------------------------------
147  {
148  std::stringstream ss;
149  ss << tx_blob;
150  binary_archive<false> ba(ss);
151  bool r = tx.serialize_base(ba);
152  CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
153  CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data");
154  tx.invalidate_hashes();
155  return true;
156  }
157  //---------------------------------------------------------------
159  {
160  std::stringstream ss;
161  ss << tx_blob;
162  binary_archive<false> ba(ss);
163  bool r = ::serialization::serialize_noeof(ba, tx);
164  CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction prefix from blob");
165  return true;
166  }
167  //---------------------------------------------------------------
169  {
170  std::stringstream ss;
171  ss << tx_blob;
172  binary_archive<false> ba(ss);
173  bool r = ::serialization::serialize(ba, tx);
174  CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
175  CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
176  tx.invalidate_hashes();
177  //TODO: validate tx
178 
179  return get_transaction_hash(tx, tx_hash);
180  }
181  //---------------------------------------------------------------
182  bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
183  {
184  if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash))
185  return false;
186  get_transaction_prefix_hash(tx, tx_prefix_hash);
187  return true;
188  }
189  //---------------------------------------------------------------
190  bool is_v1_tx(const blobdata_ref& tx_blob)
191  {
192  //TODO: Public - assure return true. Build logic for prunable v2/v3 tx data later.
193  return true;
194 
196  const char* begin = static_cast<const char*>(tx_blob.data());
197  const char* end = begin + tx_blob.size();
198  int read = tools::read_varint(begin, end, version);
199  if (read <= 0)
200  throw std::runtime_error("Internal error getting transaction version");
201  }
202  //---------------------------------------------------------------
203  bool is_v1_tx(const blobdata& tx_blob)
204  {
205  return is_v1_tx(blobdata_ref{tx_blob.data(), tx_blob.size()});
206  }
207  //---------------------------------------------------------------
208  bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const uint32_t account_major_offset)
209  {
210  crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation);
211  bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
212  if (!r)
213  {
214  MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
215  memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation));
216  }
217 
218  std::vector<crypto::key_derivation> additional_recv_derivations;
219  for (size_t i = 0; i < additional_tx_public_keys.size(); ++i)
220  {
221  crypto::key_derivation additional_recv_derivation = AUTO_VAL_INIT(additional_recv_derivation);
222  r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation);
223  if (!r)
224  {
225  MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")");
226  }
227  else
228  {
229  additional_recv_derivations.push_back(additional_recv_derivation);
230  }
231  }
232 
233  boost::optional<subaddress_receive_info> subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index,hwdev);
234  CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address");
235 
236  return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, subaddr_recv_info->index, in_ephemeral, ki, hwdev, account_major_offset);
237  }
238  //---------------------------------------------------------------
239  bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const uint32_t account_major_offset)
240  {
241  uint32_t major_index_offset_based = received_index.major + (received_index.major != 0 ? account_major_offset : 0);
242  cryptonote::subaddress_index recv_index = {major_index_offset_based, received_index.minor};
243 
244  if (hwdev.compute_key_image(ack, out_key, recv_derivation, real_output_index, recv_index, in_ephemeral, ki))
245  {
246  return true;
247  }
248 
250  {
251  // for watch-only wallet, simply copy the known output pubkey
252  in_ephemeral.pub = out_key;
253  in_ephemeral.sec = crypto::null_skey;
254  }
255  else
256  {
257  // derive secret key with subaddress - step 1: original CN derivation
258  crypto::secret_key scalar_step1;
259  hwdev.derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1); // computes Hs(a*R || idx) + b
260 
261  // step 2: add Hs(a || index_major || index_minor)
262  crypto::secret_key subaddr_sk;
263  crypto::secret_key scalar_step2;
264  if (recv_index.is_zero())
265  {
266  scalar_step2 = scalar_step1; // treat index=(0,0) as a special case representing the main address
267  }
268  else
269  {
270  subaddr_sk = hwdev.get_subaddress_secret_key(ack.m_view_secret_key, recv_index);
271  hwdev.sc_secret_add(scalar_step2, scalar_step1,subaddr_sk);
272  }
273 
274  in_ephemeral.sec = scalar_step2;
275 
276  if (ack.m_multisig_keys.empty())
277  {
278  // when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase
279  CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key");
280  }
281  else
282  {
283  // when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation
284  CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key");
285  // and don't forget to add the contribution from the subaddress part
286  if (!recv_index.is_zero())
287  {
288  crypto::public_key subaddr_pk;
289  CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key");
290  add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk);
291  }
292  }
293 
294  CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key,
295  false, "key image helper precomp: given output pubkey doesn't match the derived one");
296  }
297 
298  hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki);
299  return true;
300  }
301  //---------------------------------------------------------------
303  {
304  if(b == 0)
305  return 1;
306  uint64_t total = a;
307  for(uint64_t i = 1; i != b; i++)
308  total *= a;
309  return total;
310  }
311  //---------------------------------------------------------------
312  bool parse_amount(uint64_t& amount, const std::string& str_amount_)
313  {
314  std::string str_amount = str_amount_;
315  boost::algorithm::trim(str_amount);
316 
317  size_t point_index = str_amount.find_first_of('.');
318  size_t fraction_size;
319  if (std::string::npos != point_index)
320  {
321  fraction_size = str_amount.size() - point_index - 1;
322  while (default_decimal_point < fraction_size && '0' == str_amount.back())
323  {
324  str_amount.erase(str_amount.size() - 1, 1);
325  --fraction_size;
326  }
327  if (default_decimal_point < fraction_size)
328  return false;
329  str_amount.erase(point_index, 1);
330  }
331  else
332  {
333  fraction_size = 0;
334  }
335 
336  if (str_amount.empty())
337  return false;
338 
339  if (fraction_size < default_decimal_point)
340  {
341  str_amount.append(default_decimal_point - fraction_size, '0');
342  }
343 
344  return string_tools::get_xtype_from_string(amount, str_amount);
345  }
346  //---------------------------------------------------------------
347  uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
348  {
349  return blob_size;
350  }
351  //---------------------------------------------------------------
353  {
354  size_t blob_size;
355  if (tx.is_blob_size_valid())
356  {
357  blob_size = tx.blob_size;
358  }
359  else
360  {
361  std::ostringstream s;
363  ::serialization::serialize(a, const_cast<transaction&>(tx));
364  blob_size = s.str().size();
365  }
366  return get_transaction_weight(tx, blob_size);
367  }
368  //---------------------------------------------------------------
369  bool get_tx_fee(const transaction& tx, uint64_t & fee)
370  {
371  uint64_t amount_in = 0;
372  uint64_t amount_out = 0;
373  for(auto& in: tx.vin)
374  {
375  CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key) || in.type() == typeid(txin_to_key_public), 0, "unexpected type id in transaction");
376 
377  if(tx.version == 1 || tx.version == 2)
378  {
379  amount_in += boost::get<txin_to_key>(in).amount;
380  }
381  else
382  {
383  amount_in += boost::get<txin_to_key_public>(in).amount;
384  }
385  }
386  for(auto& o: tx.vout)
387  amount_out += o.amount;
388 
389  CHECK_AND_ASSERT_MES(amount_in >= amount_out, false, "transaction spend (" <<amount_in << ") more than it has (" << amount_out << ")");
390  fee = amount_in - amount_out;
391  return true;
392  }
393  //---------------------------------------------------------------
395  {
396  uint64_t r = 0;
397  if(!get_tx_fee(tx, r))
398  return 0;
399  return r;
400  }
401  //---------------------------------------------------------------
402  bool parse_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<tx_extra_field>& tx_extra_fields)
403  {
404  tx_extra_fields.clear();
405 
406  if(tx_extra.empty())
407  return true;
408 
409  std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
410  std::istringstream iss(extra_str);
411  binary_archive<false> ar(iss);
412 
413  bool eof = false;
414  while (!eof)
415  {
416  tx_extra_field field;
417  bool r = ::do_serialize(ar, field);
418  CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
419  tx_extra_fields.push_back(field);
420 
421  std::ios_base::iostate state = iss.rdstate();
422  eof = (EOF == iss.peek());
423  iss.clear(state);
424  }
425  CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
426 
427  return true;
428  }
429  //---------------------------------------------------------------
430  template<typename T>
431  static bool pick(binary_archive<true> &ar, std::vector<tx_extra_field> &fields, uint8_t tag)
432  {
433  std::vector<tx_extra_field>::iterator it;
434  while ((it = std::find_if(fields.begin(), fields.end(), [](const tx_extra_field &f) { return f.type() == typeid(T); })) != fields.end())
435  {
436  bool r = ::do_serialize(ar, tag);
437  CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra field");
438  r = ::do_serialize(ar, boost::get<T>(*it));
439  CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra field");
440  fields.erase(it);
441  }
442  return true;
443  }
444  //---------------------------------------------------------------
445  bool sort_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<uint8_t> &sorted_tx_extra, bool allow_partial)
446  {
447  std::vector<tx_extra_field> tx_extra_fields;
448 
449  if(tx_extra.empty())
450  {
451  sorted_tx_extra.clear();
452  return true;
453  }
454 
455  std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
456  std::istringstream iss(extra_str);
457  binary_archive<false> ar(iss);
458 
459  bool eof = false;
460  size_t processed = 0;
461  while (!eof)
462  {
463  tx_extra_field field;
464  bool r = ::do_serialize(ar, field);
465  if (!r)
466  {
467  MWARNING("failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
468  if (!allow_partial)
469  return false;
470  break;
471  }
472  tx_extra_fields.push_back(field);
473  processed = iss.tellg();
474 
475  std::ios_base::iostate state = iss.rdstate();
476  eof = (EOF == iss.peek());
477  iss.clear(state);
478  }
480  {
481  MWARNING("failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
482  if (!allow_partial)
483  return false;
484  }
485  MTRACE("Sorted " << processed << "/" << tx_extra.size());
486 
487  std::ostringstream oss;
488  binary_archive<true> nar(oss);
489 
490  // sort by:
491  if (!pick<tx_extra_pub_key>(nar, tx_extra_fields, TX_EXTRA_TAG_PUBKEY)) return false;
492  if (!pick<tx_extra_additional_pub_keys>(nar, tx_extra_fields, TX_EXTRA_TAG_ADDITIONAL_PUBKEYS)) return false;
493  if (!pick<tx_extra_nonce>(nar, tx_extra_fields, TX_EXTRA_NONCE)) return false;
494  if (!pick<tx_extra_merge_mining_tag>(nar, tx_extra_fields, TX_EXTRA_MERGE_MINING_TAG)) return false;
495  if (!pick<tx_extra_bridge_source_address>(nar, tx_extra_fields, TX_EXTRA_TAG_BRIDGE_SOURCE_ADDRESS)) return false;
496  if (!pick<tx_extra_bridge_smartchain_address>(nar, tx_extra_fields, TX_EXTRA_TAG_BRIDGE_SMARTCHAIN_ADDRESS)) return false;
497  if (!pick<tx_extra_mysterious_minergate>(nar, tx_extra_fields, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG)) return false;
498  if (!pick<tx_extra_padding>(nar, tx_extra_fields, TX_EXTRA_TAG_PADDING)) return false;
499 
500  // if not empty, someone added a new type and did not add a case above
501  if (!tx_extra_fields.empty())
502  {
503  MERROR("tx_extra_fields not empty after sorting, someone forgot to add a case above");
504  return false;
505  }
506 
507  std::string oss_str = oss.str();
508  if (allow_partial && processed < tx_extra.size())
509  {
510  MDEBUG("Appending unparsed data");
511  oss_str += std::string((const char*)tx_extra.data() + processed, tx_extra.size() - processed);
512  }
513  sorted_tx_extra = std::vector<uint8_t>(oss_str.begin(), oss_str.end());
514  return true;
515  }
516  //---------------------------------------------------------------
517  crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index)
518  {
519  std::vector<tx_extra_field> tx_extra_fields;
520  parse_tx_extra(tx_extra, tx_extra_fields);
521 
522  tx_extra_pub_key pub_key_field;
523  if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index))
524  return null_pkey;
525 
526  return pub_key_field.pub_key;
527  }
528  //---------------------------------------------------------------
530  {
531  return get_tx_pub_key_from_extra(tx_prefix.extra, pk_index);
532  }
533  //---------------------------------------------------------------
535  {
536  return get_tx_pub_key_from_extra(tx.extra, pk_index);
537  }
538  //---------------------------------------------------------------
540  {
541  return add_tx_pub_key_to_extra(tx.extra, tx_pub_key);
542  }
543  //---------------------------------------------------------------
545  {
546  return add_tx_pub_key_to_extra(tx.extra, tx_pub_key);
547  }
548  //---------------------------------------------------------------
549  bool add_tx_pub_key_to_extra(std::vector<uint8_t>& tx_extra, const crypto::public_key& tx_pub_key)
550  {
551  tx_extra.resize(tx_extra.size() + 1 + sizeof(crypto::public_key));
552  tx_extra[tx_extra.size() - 1 - sizeof(crypto::public_key)] = TX_EXTRA_TAG_PUBKEY;
553  *reinterpret_cast<crypto::public_key*>(&tx_extra[tx_extra.size() - sizeof(crypto::public_key)]) = tx_pub_key;
554  return true;
555  }
556  //---------------------------------------------------------------
557  std::vector<crypto::public_key> get_additional_tx_pub_keys_from_extra(const std::vector<uint8_t>& tx_extra)
558  {
559  // parse
560  std::vector<tx_extra_field> tx_extra_fields;
561  parse_tx_extra(tx_extra, tx_extra_fields);
562  // find corresponding field
563  tx_extra_additional_pub_keys additional_pub_keys;
564  if(!find_tx_extra_field_by_type(tx_extra_fields, additional_pub_keys))
565  return {};
566  return additional_pub_keys.data;
567  }
568  //---------------------------------------------------------------
569  std::vector<crypto::public_key> get_additional_tx_pub_keys_from_extra(const transaction_prefix& tx)
570  {
572  }
573  //---------------------------------------------------------------
574  bool add_additional_tx_pub_keys_to_extra(std::vector<uint8_t>& tx_extra, const std::vector<crypto::public_key>& additional_pub_keys)
575  {
576  // convert to variant
577  tx_extra_field field = tx_extra_additional_pub_keys{ additional_pub_keys };
578  // serialize
579  std::ostringstream oss;
580  binary_archive<true> ar(oss);
581  bool r = ::do_serialize(ar, field);
582  CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra additional tx pub keys");
583  // append
584  std::string tx_extra_str = oss.str();
585  size_t pos = tx_extra.size();
586  tx_extra.resize(tx_extra.size() + tx_extra_str.size());
587  memcpy(&tx_extra[pos], tx_extra_str.data(), tx_extra_str.size());
588  return true;
589  }
590  //---------------------------------------------------------------
591  bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce)
592  {
593  CHECK_AND_ASSERT_MES(extra_nonce.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max");
594  size_t start_pos = tx_extra.size();
595  tx_extra.resize(tx_extra.size() + 2 + extra_nonce.size());
596  //write tag
597  tx_extra[start_pos] = TX_EXTRA_NONCE;
598  //write len
599  ++start_pos;
600  tx_extra[start_pos] = static_cast<uint8_t>(extra_nonce.size());
601  //write data
602  ++start_pos;
603  memcpy(&tx_extra[start_pos], extra_nonce.data(), extra_nonce.size());
604  return true;
605  }
606  //---------------------------------------------------------------
607  bool add_bridge_source_address_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& bridge_source_address)
608  {
609  //CHECK_AND_ASSERT_MES(bridge_source_address.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max");
610  size_t start_pos = tx_extra.size();
611  tx_extra.resize(tx_extra.size() + 2 + bridge_source_address.size());
612  //write tag
613  tx_extra[start_pos] = TX_EXTRA_TAG_BRIDGE_SOURCE_ADDRESS;
614  //write len
615  ++start_pos;
616  tx_extra[start_pos] = static_cast<uint8_t>(bridge_source_address.size());
617  //write data
618  ++start_pos;
619  memcpy(&tx_extra[start_pos], bridge_source_address.data(), bridge_source_address.size());
620  return true;
621  }
622  //---------------------------------------------------------------
623  bool add_bridge_smartchain_address_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& bridge_smartchain_address)
624  {
625  //CHECK_AND_ASSERT_MES(bridge_smartchain_address.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max");
626  size_t start_pos = tx_extra.size();
627  tx_extra.resize(tx_extra.size() + 2 + bridge_smartchain_address.size());
628  //write tag
629  tx_extra[start_pos] = TX_EXTRA_TAG_BRIDGE_SMARTCHAIN_ADDRESS;
630  //write len
631  ++start_pos;
632  tx_extra[start_pos] = static_cast<uint8_t>(bridge_smartchain_address.size());
633  //write data
634  ++start_pos;
635  memcpy(&tx_extra[start_pos], bridge_smartchain_address.data(), bridge_smartchain_address.size());
636  return true;
637  }
638  //---------------------------------------------------------------
639  bool remove_field_from_tx_extra(std::vector<uint8_t>& tx_extra, const std::type_info &type)
640  {
641  if (tx_extra.empty())
642  return true;
643  std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
644  std::istringstream iss(extra_str);
645  binary_archive<false> ar(iss);
646  std::ostringstream oss;
647  binary_archive<true> newar(oss);
648 
649  bool eof = false;
650  while (!eof)
651  {
652  tx_extra_field field;
653  bool r = ::do_serialize(ar, field);
654  CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
655  if (field.type() != type)
656  ::do_serialize(newar, field);
657 
658  std::ios_base::iostate state = iss.rdstate();
659  eof = (EOF == iss.peek());
660  iss.clear(state);
661  }
662  CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
663  tx_extra.clear();
664  std::string s = oss.str();
665  tx_extra.reserve(s.size());
666  std::copy(s.begin(), s.end(), std::back_inserter(tx_extra));
667  return true;
668  }
669  //---------------------------------------------------------------
670  void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id)
671  {
672  extra_nonce.clear();
673  extra_nonce.push_back(TX_EXTRA_NONCE_PAYMENT_ID);
674  const uint8_t* payment_id_ptr = reinterpret_cast<const uint8_t*>(&payment_id);
675  std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce));
676  }
677  //---------------------------------------------------------------
679  {
680  extra_nonce.clear();
681  extra_nonce.push_back(TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID);
682  const uint8_t* payment_id_ptr = reinterpret_cast<const uint8_t*>(&payment_id);
683  std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce));
684  }
685  //---------------------------------------------------------------
686  bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id)
687  {
688  if(sizeof(crypto::hash) + 1 != extra_nonce.size())
689  return false;
690  if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0])
691  return false;
692  payment_id = *reinterpret_cast<const crypto::hash*>(extra_nonce.data() + 1);
693  return true;
694  }
695  //---------------------------------------------------------------
697  {
698  if(sizeof(crypto::hash8) + 1 != extra_nonce.size())
699  return false;
700  if (TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID != extra_nonce[0])
701  return false;
702  payment_id = *reinterpret_cast<const crypto::hash8*>(extra_nonce.data() + 1);
703  return true;
704  }
705  //---------------------------------------------------------------
707  {
708  etn = 0;
709  if(tx.version == 1 || tx.version == 2) {
710  for(const auto& in: tx.vin)
711  {
712  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
713  etn += tokey_in.amount;
714  }
715  }
716  else //tx.version >= 3 (public transactions: can spend only new inputs)
717  {
718  for(const auto& in: tx.vin)
719  {
720  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key_public, tokey_in, false);
721  etn += tokey_in.amount;
722  }
723  }
724 
725  return true;
726  }
727  //---------------------------------------------------------------
729  {
730  CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, 0, "wrong miner tx in block: " << get_block_hash(b) << ", b.miner_tx.vin.size() != 1");
731  CHECKED_GET_SPECIFIC_VARIANT(b.miner_tx.vin[0], const txin_gen, coinbase_in, 0);
732  return coinbase_in.height;
733  }
734  //---------------------------------------------------------------
736  {
737  for(const auto& in: tx.vin)
738  {
739  if (tx.version == 1 || tx.version == 2)
740  {
741  CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key), false, "wrong variant type: "
742  << in.type().name() << ", expected " << typeid(txin_to_key).name()
743  << ", in transaction id=" << get_transaction_hash(tx));
744  }
745  else //tx.version >= 3 (public transactions: can spend only new inputs)
746  {
747  CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key_public), false, "wrong variant type: "
748  << in.type().name() << ", expected " << typeid(txin_to_key_public).name()
749  << ", in transaction id=" << get_transaction_hash(tx));
750  }
751  }
752  return true;
753  }
754  //-----------------------------------------------------------------------------------------------
756  {
757  for(const tx_out& out: tx.vout)
758  {
759  if (tx.version == 1)
760  {
761  CHECK_AND_ASSERT_MES(out.target.type() == typeid(txout_to_key), false, "wrong variant type: "
762  << out.target.type().name() << ", expected " << typeid(txout_to_key).name()
763  << ", in transaction id=" << get_transaction_hash(tx));
764 
765  CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx));
766 
767  if(!check_key(boost::get<txout_to_key>(out.target).key))
768  return false;
769  }
770  else //tx.version >= 2 (public transactions: only new public outputs are allowed)
771  {
772  CHECK_AND_ASSERT_MES(out.target.type() == typeid(txout_to_key_public), false, "wrong variant type: "
773  << out.target.type().name() << ", expected " << typeid(txout_to_key_public).name()
774  << ", in transaction id=" << get_transaction_hash(tx));
775 
776  CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx));
777 
778  if(!check_key(boost::get<txout_to_key_public>(out.target).address.m_spend_public_key) ||
779  !check_key(boost::get<txout_to_key_public>(out.target).address.m_view_public_key))
780  return false;
781  }
782 
783  }
784  return true;
785  }
786  //-----------------------------------------------------------------------------------------------
788  {
789  return check_inputs_overflow(tx) && check_outs_overflow(tx);
790  }
791  //---------------------------------------------------------------
793  {
794  uint64_t etn = 0;
795  if(tx.version >= 3)
796  {
797  for(const auto& in: tx.vin)
798  {
799  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key_public, tokey_in, false);
800  if(etn > tokey_in.amount + etn)
801  return false;
802  etn += tokey_in.amount;
803  }
804  return true;
805  }
806 
807  for(const auto& in: tx.vin)
808  {
809  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
810  if(etn > tokey_in.amount + etn)
811  return false;
812  etn += tokey_in.amount;
813  }
814  return true;
815  }
816  //---------------------------------------------------------------
818  {
819  uint64_t etn = 0;
820  for(const auto& o: tx.vout)
821  {
822  if(etn > o.amount + etn)
823  return false;
824  etn += o.amount;
825  }
826  return true;
827  }
828  //---------------------------------------------------------------
830  {
831  uint64_t outputs_amount = 0;
832  for(const auto& o: tx.vout)
833  outputs_amount += o.amount;
834  return outputs_amount;
835  }
836  //---------------------------------------------------------------
838  {
840  CHECK_AND_ASSERT_MES(res.size() == 64, res, "wrong hash256 with string_tools::pod_to_hex conversion");
841  auto erased_pos = res.erase(8, 48);
842  res.insert(8, "....");
843  return res;
844  }
845  //---------------------------------------------------------------
846  bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index)
847  {
848  crypto::key_derivation derivation;
849  bool r = acc.get_device().generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
850  CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
853  CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
854  if (pk == out_key.key)
855  return true;
856  // try additional tx pubkeys if available
857  if (!additional_tx_pub_keys.empty())
858  {
859  CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys");
860  r = acc.get_device().generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation);
861  CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
863  CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
864  return pk == out_key.key;
865  }
866  return false;
867  }
868  //---------------------------------------------------------------
869  boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev)
870  {
871  // try the shared tx pubkey
872  crypto::public_key subaddress_spendkey;
873  hwdev.derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey);
874  auto found = subaddresses.find(subaddress_spendkey);
875  if (found != subaddresses.end())
876  return subaddress_receive_info{ found->second, derivation };
877  // try additional tx pubkeys if available
878  if (!additional_derivations.empty())
879  {
880  CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations");
881  hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey);
882  found = subaddresses.find(subaddress_spendkey);
883  if (found != subaddresses.end())
884  return subaddress_receive_info{ found->second, additional_derivations[output_index] };
885  }
886  return boost::none;
887  }
888  //---------------------------------------------------------------
889  boost::optional<subaddress_receive_info> is_out_to_acc_precomp_public(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const cryptonote::account_public_address output_address)
890  {
891  crypto::public_key subaddress_spendkey = output_address.m_spend_public_key;
892  auto found = subaddresses.find(subaddress_spendkey);
893  if (found != subaddresses.end()){
894  return subaddress_receive_info{found->second, {}};
895  }
896  return boost::none;
897  }
898  //---------------------------------------------------------------
899  bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& etn_transfered)
900  {
902  if(null_pkey == tx_pub_key)
903  return false;
904  std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
905  return lookup_acc_outs(acc, tx, tx_pub_key, additional_tx_pub_keys, outs, etn_transfered);
906  }
907  //---------------------------------------------------------------
908  bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, std::vector<size_t>& outs, uint64_t& etn_transfered)
909  {
910  CHECK_AND_ASSERT_MES(additional_tx_pub_keys.empty() || additional_tx_pub_keys.size() == tx.vout.size(), false, "wrong number of additional pubkeys" );
911  etn_transfered = 0;
912  size_t i = 0;
913  for(const tx_out& o: tx.vout)
914  {
915  CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "wrong type id in transaction out" );
916  if(is_out_to_acc(acc, boost::get<txout_to_key>(o.target), tx_pub_key, additional_tx_pub_keys, i))
917  {
918  outs.push_back(i);
919  etn_transfered += o.amount;
920  }
921  i++;
922  }
923  return true;
924  }
925  //---------------------------------------------------------------
927  {
928  cn_fast_hash(blob.data(), blob.size(), res);
929  }
930  //---------------------------------------------------------------
932  {
933  cn_fast_hash(blob.data(), blob.size(), res);
934  }
935  //---------------------------------------------------------------
936  void set_default_decimal_point(unsigned int decimal_point)
937  {
938  switch (decimal_point)
939  {
940  case 2:
941  default_decimal_point = decimal_point;
942  break;
943  default:
944  ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point);
945  }
946  }
947  //---------------------------------------------------------------
949  {
950  return default_decimal_point;
951  }
952  //---------------------------------------------------------------
953  std::string get_unit(unsigned int decimal_point)
954  {
955  if (decimal_point == (unsigned int)-1)
956  decimal_point = default_decimal_point;
957  switch (decimal_point)
958  {
959  case 2:
960  return "electroneum";
961  case 0:
962  return "ecent";
963  default:
964  ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point);
965  }
966  }
967  //---------------------------------------------------------------
968  std::string print_etn(uint64_t amount, unsigned int decimal_point)
969  {
970  if (decimal_point == (unsigned int)-1)
971  decimal_point = default_decimal_point;
972  std::string s = std::to_string(amount);
973  if(s.size() < decimal_point+1)
974  {
975  s.insert(0, decimal_point+1 - s.size(), '0');
976  }
977  if (decimal_point > 0)
978  s.insert(s.size() - decimal_point, ".");
979  return s;
980  }
981  //---------------------------------------------------------------
983  {
984  crypto::hash h = null_hash;
985  get_blob_hash(blob, h);
986  return h;
987  }
988  //---------------------------------------------------------------
990  {
991  crypto::hash h = null_hash;
992  get_blob_hash(blob, h);
993  return h;
994  }
995  //---------------------------------------------------------------
997  {
998  crypto::hash h = null_hash;
999  get_transaction_hash(t, h, NULL);
1000  CHECK_AND_ASSERT_THROW_MES(get_transaction_hash(t, h, NULL), "Failed to calculate transaction hash");
1001  return h;
1002  }
1003  //---------------------------------------------------------------
1005  {
1006  return get_transaction_hash(t, res, NULL);
1007  }
1008  //---------------------------------------------------------------
1010  {
1011  if (t.version == 1)
1012  return false;
1013  const unsigned int unprunable_size = t.unprunable_size;
1014  if (blob && unprunable_size)
1015  {
1016  CHECK_AND_ASSERT_MES(unprunable_size <= blob->size(), false, "Inconsistent transaction unprunable and blob sizes");
1017  cryptonote::get_blob_hash(epee::span<const char>(blob->data() + unprunable_size, blob->size() - unprunable_size), res);
1018  }
1019  else
1020  {
1021  transaction &tt = const_cast<transaction&>(t);
1022  std::stringstream ss;
1023  binary_archive<true> ba(ss);
1024  const size_t inputs = t.vin.size();
1025  const size_t outputs = t.vout.size();
1026  const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
1027  bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
1028  CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
1029  cryptonote::get_blob_hash(ss.str(), res);
1030  }
1031  return true;
1032  }
1033  //---------------------------------------------------------------
1035  {
1036  crypto::hash res;
1037  CHECK_AND_ASSERT_THROW_MES(calculate_transaction_prunable_hash(t, blobdata, res), "Failed to calculate tx prunable hash");
1038  return res;
1039  }
1040  //---------------------------------------------------------------
1042  {
1043  // v1 transactions hash the entire blob
1044  CHECK_AND_ASSERT_THROW_MES(t.version > 1, "Hash for pruned v1 tx cannot be calculated");
1045 
1046  // v2 transactions hash different parts together, than hash the set of those hashes
1047  crypto::hash hashes[3];
1048 
1049  // prefix
1051 
1052  transaction &tt = const_cast<transaction&>(t);
1053 
1054  // base rct
1055  {
1056  std::stringstream ss;
1057  binary_archive<true> ba(ss);
1058  const size_t inputs = t.vin.size();
1059  const size_t outputs = t.vout.size();
1060  bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs);
1061  CHECK_AND_ASSERT_THROW_MES(r, "Failed to serialize rct signatures base");
1062  cryptonote::get_blob_hash(ss.str(), hashes[1]);
1063  }
1064 
1065  // prunable rct
1067  hashes[2] = crypto::null_hash;
1068  else
1069  hashes[2] = pruned_data_hash;
1070 
1071  // the tx hash is the hash of the 3 hashes
1073  return res;
1074  }
1075  //---------------------------------------------------------------
1076  bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
1077  {
1078  // v1 transactions hash the entire blob
1079  if (t.version == 1)
1080  {
1081  size_t ignored_blob_size, &blob_size_ref = blob_size ? *blob_size : ignored_blob_size;
1082  return get_object_hash(t, res, blob_size_ref);
1083  }
1084 
1085  // v2 transactions hash different parts together, than hash the set of those hashes
1086  crypto::hash hashes[3];
1087 
1088  // prefix
1090 
1091  const blobdata blob = tx_to_blob(t);
1092  const unsigned int unprunable_size = t.unprunable_size;
1093  const unsigned int prefix_size = t.prefix_size;
1094 
1095  // base rct
1096  CHECK_AND_ASSERT_MES(prefix_size <= unprunable_size && unprunable_size <= blob.size(), false, "Inconsistent transaction prefix, unprunable and blob sizes");
1097  cryptonote::get_blob_hash(epee::span<const char>(blob.data() + prefix_size, unprunable_size - prefix_size), hashes[1]);
1098 
1099  // prunable rct
1101  {
1102  hashes[2] = crypto::null_hash;
1103  }
1104  else
1105  {
1106  CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, &blob, hashes[2]), false, "Failed to get tx prunable hash");
1107  }
1108 
1109  // the tx hash is the hash of the 3 hashes
1110  res = cn_fast_hash(hashes, sizeof(hashes));
1111 
1112  // we still need the size
1113  if (blob_size)
1114  {
1115  if (!t.is_blob_size_valid())
1116  {
1117  t.blob_size = blob.size();
1118  t.set_blob_size_valid(true);
1119  }
1120  *blob_size = t.blob_size;
1121  }
1122 
1123  return true;
1124  }
1125  //---------------------------------------------------------------
1126  bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
1127  {
1128  if (t.is_hash_valid())
1129  {
1130 #ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK
1131  CHECK_AND_ASSERT_THROW_MES(!calculate_transaction_hash(t, res, blob_size) || t.hash == res, "tx hash cash integrity failure");
1132 #endif
1133  res = t.hash;
1134  if (blob_size)
1135  {
1136  if (!t.is_blob_size_valid())
1137  {
1139  t.set_blob_size_valid(true);
1140  }
1141  *blob_size = t.blob_size;
1142  }
1143  ++tx_hashes_cached_count;
1144  return true;
1145  }
1146  ++tx_hashes_calculated_count;
1147  bool ret = calculate_transaction_hash(t, res, blob_size);
1148  if (!ret)
1149  return false;
1150  t.hash = res;
1151  t.set_hash_valid(true);
1152  if (blob_size)
1153  {
1154  t.blob_size = *blob_size;
1155  t.set_blob_size_valid(true);
1156  }
1157  return true;
1158  }
1159  //---------------------------------------------------------------
1160  bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
1161  {
1162  return get_transaction_hash(t, res, &blob_size);
1163  }
1164  //---------------------------------------------------------------
1166  {
1167  blobdata blob = t_serializable_object_to_blob(static_cast<block_header>(b));
1168  crypto::hash tree_root_hash = get_tx_tree_hash(b);
1169  blob.append(reinterpret_cast<const char*>(&tree_root_hash), sizeof(tree_root_hash));
1170  blob.append(tools::get_varint_data(b.tx_hashes.size()+1));
1171  return blob;
1172  }
1173  //---------------------------------------------------------------
1174  bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob)
1175  {
1177  }
1178  //---------------------------------------------------------------
1180  {
1181  if (b.is_hash_valid())
1182  {
1183 #ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK
1184  CHECK_AND_ASSERT_THROW_MES(!calculate_block_hash(b, res) || b.hash == res, "block hash cash integrity failure");
1185 #endif
1186  res = b.hash;
1187  ++block_hashes_cached_count;
1188  return true;
1189  }
1190  ++block_hashes_calculated_count;
1191  bool ret = calculate_block_hash(b, res);
1192  if (!ret)
1193  return false;
1194  b.hash = res;
1195  b.set_hash_valid(true);
1196  return true;
1197  }
1198  //---------------------------------------------------------------
1200  {
1201  crypto::hash p = null_hash;
1202  get_block_hash(b, p);
1203  return p;
1204  }
1205  //---------------------------------------------------------------
1207  {
1209  const int cn_variant = b.major_version == 6 ? b.major_version - 5 : 0; // Emergency HF so anti-asic is only if HF 6
1210  crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant);
1211  return true;
1212  }
1213  //---------------------------------------------------------------
1214  std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
1215  {
1216  std::vector<uint64_t> res = off;
1217  for(size_t i = 1; i < res.size(); i++)
1218  res[i] += res[i-1];
1219  return res;
1220  }
1221  //---------------------------------------------------------------
1222  std::vector<uint64_t> absolute_output_offsets_to_relative(const std::vector<uint64_t>& off)
1223  {
1224  std::vector<uint64_t> res = off;
1225  if(!off.size())
1226  return res;
1227  std::sort(res.begin(), res.end());//just to be sure, actually it is already should be sorted
1228  for(size_t i = res.size()-1; i != 0; i--)
1229  res[i] -= res[i-1];
1230 
1231  return res;
1232  }
1233  //---------------------------------------------------------------
1235  {
1236  crypto::hash p = null_hash;
1237  get_block_longhash(b, p, height);
1238  return p;
1239  }
1240  //---------------------------------------------------------------
1241  bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash)
1242  {
1243  std::stringstream ss;
1244  ss << b_blob;
1245  binary_archive<false> ba(ss);
1246  bool r = ::serialization::serialize(ba, b);
1247  CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob");
1248  b.invalidate_hashes();
1250  if (block_hash)
1251  {
1252  calculate_block_hash(b, *block_hash, &b_blob);
1253  ++block_hashes_calculated_count;
1254  b.hash = *block_hash;
1255  b.set_hash_valid(true);
1256  }
1257  return true;
1258  }
1259  //---------------------------------------------------------------
1261  {
1262  return parse_and_validate_block_from_blob(b_blob, b, NULL);
1263  }
1264  //---------------------------------------------------------------
1265  bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash)
1266  {
1267  return parse_and_validate_block_from_blob(b_blob, b, &block_hash);
1268  }
1269  //---------------------------------------------------------------
1271  {
1273  }
1274  //---------------------------------------------------------------
1275  bool block_to_blob(const block& b, blobdata& b_blob)
1276  {
1277  return t_serializable_object_to_blob(b, b_blob);
1278  }
1279  //---------------------------------------------------------------
1281  {
1282  return t_serializable_object_to_blob(tx);
1283  }
1284  //---------------------------------------------------------------
1285  bool tx_to_blob(const transaction& tx, blobdata& b_blob)
1286  {
1287  return t_serializable_object_to_blob(tx, b_blob);
1288  }
1289  //---------------------------------------------------------------
1290  void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h)
1291  {
1292  tree_hash(tx_hashes.data(), tx_hashes.size(), h);
1293  }
1294  //---------------------------------------------------------------
1295  crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes)
1296  {
1297  crypto::hash h = null_hash;
1298  get_tx_tree_hash(tx_hashes, h);
1299  return h;
1300  }
1301  //---------------------------------------------------------------
1303  {
1304  std::vector<crypto::hash> txs_ids;
1305  txs_ids.reserve(1 + b.tx_hashes.size());
1306  crypto::hash h = null_hash;
1307  size_t bl_sz = 0;
1308  CHECK_AND_ASSERT_THROW_MES(get_transaction_hash(b.miner_tx, h, bl_sz), "Failed to calculate transaction hash");
1309  txs_ids.push_back(h);
1310  for(auto& th: b.tx_hashes)
1311  txs_ids.push_back(th);
1312  return get_tx_tree_hash(txs_ids);
1313  }
1314  //---------------------------------------------------------------
1316  {
1317  const uint64_t *begin = valid_decomposed_outputs;
1318  const uint64_t *end = valid_decomposed_outputs + sizeof(valid_decomposed_outputs) / sizeof(valid_decomposed_outputs[0]);
1319  return std::binary_search(begin, end, amount);
1320  }
1321  //---------------------------------------------------------------
1322  void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t & block_hashes_cached)
1323  {
1324  tx_hashes_calculated = tx_hashes_calculated_count;
1325  tx_hashes_cached = tx_hashes_cached_count;
1326  block_hashes_calculated = block_hashes_calculated_count;
1327  block_hashes_cached = block_hashes_cached_count;
1328  }
1329  //---------------------------------------------------------------
1331  {
1333  crypto::cn_slow_hash(passphrase.data(), passphrase.size(), hash);
1334  sc_add((unsigned char*)key.data, (const unsigned char*)key.data, (const unsigned char*)hash.data);
1335  return key;
1336  }
1337  //---------------------------------------------------------------
1339  {
1341  crypto::cn_slow_hash(passphrase.data(), passphrase.size(), hash);
1342  sc_sub((unsigned char*)key.data, (const unsigned char*)key.data, (const unsigned char*)hash.data);
1343  return key;
1344  }
1345 }
const char * res
Definition: hmac_keccak.cpp:41
crypto::public_key pub
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
#define MERROR(x)
Definition: misc_log_ex.h:73
virtual bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub)=0
bool generate_key_image_helper_precomp(const account_keys &ack, const crypto::public_key &out_key, const crypto::key_derivation &recv_derivation, size_t real_output_index, const subaddress_index &received_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
bool check_outs_overflow(const transaction &tx)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash &block_hash)
POD_CLASS ec_point
Definition: crypto.h:70
const uint32_t T[512]
std::vector< crypto::hash > tx_hashes
#define TX_EXTRA_MYSTERIOUS_MINERGATE_TAG
Definition: tx_extra.h:45
crypto::public_key get_tx_pub_key_from_extra(const transaction &tx, size_t pk_index)
#define ASSERT_MES_AND_THROW(message)
Definition: misc_log_ex.h:172
#define TX_EXTRA_TAG_BRIDGE_SOURCE_ADDRESS
Definition: tx_extra.h:43
size_t size() const noexcept
#define MTRACE(x)
Definition: misc_log_ex.h:77
std::vector< crypto::public_key > data
Definition: tx_extra.h:169
bool check_outs_valid(const transaction &tx)
crypto::hash get_transaction_prefix_hash(const transaction_prefix &tx)
crypto::secret_key sec
crypto::hash get_blob_hash(const epee::span< const char > &blob)
virtual bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b)=0
void get_blob_hash(const epee::span< const char > &blob, crypto::hash &res)
void set_blob_size(size_t sz)
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
::std::string string
Definition: gtest-port.h:1097
uint64_t get_outs_etn_amount(const transaction &tx)
crypto::public_key pub_key
Definition: tx_extra.h:101
POD_CLASS key_derivation
Definition: crypto.h:98
std::string print_etn(uint64_t amount, unsigned int decimal_point)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
bool check_stream_state(Archive &ar, bool noeof=false)
size_t get_object_blobsize(const t_object &o)
uint64_t height
Definition: blockchain.cpp:91
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *)
#define CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:189
bool add_bridge_smartchain_address_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &bridge_smartchain_address)
boost::variant< tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag, tx_extra_additional_pub_keys, tx_extra_bridge_source_address, tx_extra_bridge_smartchain_address, tx_extra_mysterious_minergate > tx_extra_field
Definition: tx_extra.h:207
bool parse_and_validate_tx_prefix_from_blob(const blobdata &tx_blob, transaction_prefix &tx)
bool add_tx_pub_key_to_extra(std::vector< uint8_t > &tx_extra, const crypto::public_key &tx_pub_key)
bool is_v1_tx(const blobdata &tx_blob)
const char * key
Definition: hmac_keccak.cpp:39
bool add_bridge_source_address_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &bridge_source_address)
crypto namespace.
Definition: crypto.cpp:58
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
uint64_t get_transaction_weight(const transaction &tx)
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
bool add_additional_tx_pub_keys_to_extra(std::vector< uint8_t > &tx_extra, const std::vector< crypto::public_key > &additional_pub_keys)
std::string get_unit(unsigned int decimal_point)
bool expand_transaction_1(transaction &tx, bool base_only)
unsigned char uint8_t
Definition: stdint.h:124
bool get_object_hash(const t_object &o, crypto::hash &res)
crypto::secret_key encrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase)
uint8_t type
Definition: rctTypes.h:241
std::string & trim(std::string &str)
Definition: string_tools.h:288
const char * name
struct hash_func hashes[]
bool calculate_transaction_hash(const transaction &t, crypto::hash &res, size_t *blob_size)
void copy(key &AA, const key &A)
Definition: rctOps.h:79
virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation)=0
std::vector< uint8_t > extra
#define MDEBUG(x)
Definition: misc_log_ex.h:76
Archiver & operator &(Archiver &ar, Student &s)
constexpr std::size_t size() const noexcept
Definition: span.h:111
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
const crypto::secret_key null_skey
Definition: crypto.cpp:73
bool is_hash_valid() const
#define TX_EXTRA_NONCE_MAX_COUNT
Definition: tx_extra.h:36
uint64_t power_integral(uint64_t a, uint64_t b)
boost::optional< subaddress_receive_info > is_out_to_acc_precomp(const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, size_t output_index, hw::device &hwdev)
bool parse_amount(uint64_t &amount, const std::string &str_amount_)
bool is_valid_decomposed_amount(uint64_t amount)
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
bool calculate_transaction_prunable_hash(const transaction &t, const cryptonote::blobdata *blob, crypto::hash &res)
unsigned int get_default_decimal_point()
rctSigPrunable p
Definition: rctTypes.h:437
void set_blob_size_valid(bool v) const
virtual bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub)=0
unsigned int uint32_t
Definition: stdint.h:126
const crypto::public_key null_pkey
Definition: crypto.cpp:72
void cn_fast_hash(const void *data, size_t length, char *hash)
crypto::hash get_block_longhash(const block &b, uint64_t height)
bool check_inputs_types_supported(const transaction &tx)
bool generate_key_image_helper(const account_keys &ack, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
void set_hash_valid(bool v) const
std::string get_varint_data(const T &v)
Returns the string that represents the varint.
Definition: varint.h:85
std::vector< uint64_t > absolute_output_offsets_to_relative(const std::vector< uint64_t > &off)
void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization::version_type ver)
#define TX_EXTRA_MERGE_MINING_TAG
Definition: tx_extra.h:41
blobdata get_block_hashing_blob(const block &b)
#define TX_EXTRA_TAG_PADDING
Definition: tx_extra.h:38
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub)=0
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
virtual bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image)=0
bool get_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash &payment_id)
#define ge_p1p1_to_p3
Definition: ge.h:63
bool serialize_rctsig_base(Archive< W > &ar, size_t inputs, size_t outputs)
Definition: rctTypes.h:251
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
#define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID
Definition: tx_extra.h:48
crypto::hash get_pruned_transaction_hash(const transaction &t, const crypto::hash &pruned_data_hash)
POD_CLASS public_key
Definition: crypto.h:76
#define TX_EXTRA_TAG_PUBKEY
Definition: tx_extra.h:39
#define ge_add
Definition: ge.h:69
#define TX_EXTRA_TAG_ADDITIONAL_PUBKEYS
Definition: tx_extra.h:42
version
Supported socks variants.
Definition: socks.h:57
void set_default_decimal_point(unsigned int decimal_point)
#define MWARNING(x)
Definition: misc_log_ex.h:74
void do_serialize(boost::mpl::false_, Archive &a, epee::net_utils::network_address &na)
void cn_fast_hash(const void *data, size_t length, char *hash)
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash8 &payment_id)
#define TX_EXTRA_NONCE
Definition: tx_extra.h:40
void tree_hash(const char(*hashes)[HASH_SIZE], size_t count, char *root_hash)
bool tx_to_blob(const transaction &tx, blobdata &b_blob)
#define ge_p3_to_cached
Definition: ge.h:61
#define ge_p3_tobytes
Definition: ge.h:55
crypto::secret_key m_view_secret_key
Definition: account.h:45
bool check_inputs_overflow(const transaction &tx)
virtual bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec)=0
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
std::string blobdata
Definition: blobdatatype.h:39
std::atomic< unsigned int > prefix_size
bool get_transaction_hash(const transaction &t, crypto::hash &res, size_t &blob_size)
account_public_address m_account_address
Definition: account.h:43
bool is_out_to_acc(const account_keys &acc, const txout_to_key &out_key, const crypto::public_key &tx_pub_key, const std::vector< crypto::public_key > &additional_tx_pub_keys, size_t output_index)
bool lookup_acc_outs(const account_keys &acc, const transaction &tx, const crypto::public_key &tx_pub_key, const std::vector< crypto::public_key > &additional_tx_pub_keys, std::vector< size_t > &outs, uint64_t &etn_transfered)
key identity()
Definition: rctOps.h:73
POD_CLASS hash8
Definition: hash.h:53
crypto::public_key key
#define CHECK_AND_NO_ASSERT_MES_L1(expr, fail_ret_val, message)
Definition: misc_log_ex.h:193
bool sort_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< uint8_t > &sorted_tx_extra, bool allow_partial)
Definition: blake256.h:37
std::string buff_to_hex_nodelimer(const std::string &src)
Definition: string_tools.h:87
POD_CLASS key_image
Definition: crypto.h:102
void * memcpy(void *a, const void *b, size_t c)
Matcher< T > A()
txout_target_v target
crypto::secret_key m_spend_secret_key
Definition: account.h:44
bool serialize_rctsig_prunable(Archive< W > &ar, uint8_t type, size_t inputs, size_t outputs, size_t mixin)
Definition: rctTypes.h:325
virtual bool compute_key_image(const cryptonote::account_keys &ack, const crypto::public_key &out_key, const crypto::key_derivation &recv_derivation, size_t real_output_index, const cryptonote::subaddress_index &received_index, cryptonote::keypair &in_ephemeral, crypto::key_image &ki)
Definition: device.hpp:246
bool remove_field_from_tx_extra(std::vector< uint8_t > &tx_extra, const std::type_info &type)
bool check_key(const public_key &key)
Definition: crypto.h:256
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
void set_hash_valid(bool v) const
bool check_etn_overflow(const transaction &tx)
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const transaction_prefix &tx)
std::vector< crypto::secret_key > m_multisig_keys
Definition: account.h:46
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
virtual crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index)=0
crypto::hash get_block_hash(uint64_t height)
crypto::secret_key decrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase)
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
POD_CLASS hash
Definition: hash.h:50
uint64_t get_tx_fee(const transaction &tx)
void set_encrypted_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash8 &payment_id)
crypto::hash get_tx_tree_hash(const block &b)
#define TX_EXTRA_NONCE_PAYMENT_ID
Definition: tx_extra.h:47
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height)
std::string to_string(t_connection_type type)
#define TX_EXTRA_TAG_BRIDGE_SMARTCHAIN_ADDRESS
Definition: tx_extra.h:44
void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t &block_hashes_cached)
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
boost::optional< subaddress_receive_info > is_out_to_acc_precomp_public(const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const cryptonote::account_public_address output_address)
crypto::hash get_transaction_prunable_hash(const transaction &t, const cryptonote::blobdata *blobdata)
const char * data() const noexcept
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
PUSH_WARNINGS bool get_xtype_from_string(OUT XType &val, const std::string &str_id)
Definition: string_tools.h:125
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx, crypto::hash &tx_hash, crypto::hash &tx_prefix_hash)
hw::device & get_device() const
Definition: account.cpp:59
bool calculate_block_hash(const block &b, crypto::hash &res, const blobdata *blob)
bool serialize_noeof(Archive &ar, T &v)
std::atomic< unsigned int > unprunable_size
uint64_t get_block_height(const block &b)
#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message)
std::string short_hash_str(const crypto::hash &h)
bool block_to_blob(const block &b, blobdata &b_blob)
constexpr pointer data() const noexcept
Definition: span.h:110