Electroneum
tx_validation.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 "chaingen.h"
33 #include "tx_validation.h"
34 #include "device/device.hpp"
35 
36 using namespace epee;
37 using namespace crypto;
38 using namespace cryptonote;
39 
40 namespace
41 {
42  struct tx_builder
43  {
44  void step1_init(size_t version = 1, uint64_t unlock_time = 0)
45  {
46  m_tx.vin.clear();
47  m_tx.vout.clear();
48  m_tx.signatures.clear();
49 
50  m_tx.version = version;
51  m_tx.unlock_time = unlock_time;
52 
53  m_tx_key = keypair::generate(hw::get_device("default"));
54  add_tx_pub_key_to_extra(m_tx, m_tx_key.pub);
55  }
56 
57  void step2_fill_inputs(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources)
58  {
59  BOOST_FOREACH(const tx_source_entry& src_entr, sources)
60  {
61  m_in_contexts.push_back(keypair());
62  keypair& in_ephemeral = m_in_contexts.back();
64  std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
65  subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0};
66  auto& out_key = reinterpret_cast<const crypto::public_key&>(src_entr.outputs[src_entr.real_output].second.dest);
67  generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral, img, hw::get_device(("default")));
68 
69  // put key image into tx input
70  txin_to_key input_to_key;
71  input_to_key.amount = src_entr.amount;
72  input_to_key.k_image = img;
73 
74  // fill outputs array and use relative offsets
75  BOOST_FOREACH(const tx_source_entry::output_entry& out_entry, src_entr.outputs)
76  input_to_key.key_offsets.push_back(out_entry.first);
77 
78  input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets);
79  m_tx.vin.push_back(input_to_key);
80  }
81  }
82 
83  void step3_fill_outputs(const std::vector<tx_destination_entry>& destinations)
84  {
85  size_t output_index = 0;
86  BOOST_FOREACH(const tx_destination_entry& dst_entr, destinations)
87  {
88  crypto::key_derivation derivation;
89  crypto::public_key out_eph_public_key;
90  crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, m_tx_key.sec, derivation);
91  crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
92 
93  tx_out out;
94  out.amount = dst_entr.amount;
95  txout_to_key tk;
96  tk.key = out_eph_public_key;
97  out.target = tk;
98  m_tx.vout.push_back(out);
99  output_index++;
100  }
101  }
102 
103  void step4_calc_hash()
104  {
105  get_transaction_prefix_hash(m_tx, m_tx_prefix_hash);
106  }
107 
108  void step5_sign(const std::vector<tx_source_entry>& sources)
109  {
110  m_tx.signatures.clear();
111 
112  size_t i = 0;
113  BOOST_FOREACH(const tx_source_entry& src_entr, sources)
114  {
115  std::vector<const crypto::public_key*> keys_ptrs;
116  std::vector<crypto::public_key> keys(src_entr.outputs.size());
117  size_t j = 0;
118  BOOST_FOREACH(const tx_source_entry::output_entry& o, src_entr.outputs)
119  {
120  keys[j] = rct::rct2pk(o.second.dest);
121  keys_ptrs.push_back(&keys[j]);
122  ++j;
123  }
124 
125  m_tx.signatures.push_back(std::vector<crypto::signature>());
126  std::vector<crypto::signature>& sigs = m_tx.signatures.back();
127  sigs.resize(src_entr.outputs.size());
128  generate_ring_signature(m_tx_prefix_hash, boost::get<txin_to_key>(m_tx.vin[i]).k_image, keys_ptrs, m_in_contexts[i].sec, src_entr.real_output, sigs.data());
129  i++;
130  }
131  }
132 
133  transaction m_tx;
134  keypair m_tx_key;
135  std::vector<keypair> m_in_contexts;
136  crypto::hash m_tx_prefix_hash;
137  };
138 
139  transaction make_simple_tx_with_unlock_time(const std::vector<test_event_entry>& events,
140  const cryptonote::block& blk_head, const cryptonote::account_base& from, const cryptonote::account_base& to,
141  uint64_t amount, uint64_t unlock_time)
142  {
143  std::vector<tx_source_entry> sources;
144  std::vector<tx_destination_entry> destinations;
145  fill_tx_sources_and_destinations(events, blk_head, from, to, amount, TESTS_DEFAULT_FEE, 0, sources, destinations);
146 
147  tx_builder builder;
148  builder.step1_init(1, unlock_time);
149  builder.step2_fill_inputs(from.get_keys(), sources);
150  builder.step3_fill_outputs(destinations);
151  builder.step4_calc_hash();
152  builder.step5_sign(sources);
153  return builder.m_tx;
154  };
155 
156  crypto::public_key generate_invalid_pub_key()
157  {
158  for (int i = 0; i <= 0xFF; ++i)
159  {
161  memset(&key, i, sizeof(crypto::public_key));
162  if (!crypto::check_key(key))
163  {
164  return key;
165  }
166  }
167 
168  throw std::runtime_error("invalid public key wasn't found");
169  return crypto::public_key();
170  }
171 
172  crypto::key_image generate_invalid_key_image()
173  {
175  // a random key image plucked from the blockchain
176  if (!epee::string_tools::hex_to_pod("6b9f5d1be7c950dc6e4e258c6ef75509412ba9ecaaf90e6886140151d1365b5e", key_image))
177  throw std::runtime_error("invalid key image wasn't found");
178  return key_image;
179  }
180 }
181 
182 //----------------------------------------------------------------------------------------------------------------------
183 // Tests
184 
185 bool gen_tx_big_version::generate(std::vector<test_event_entry>& events) const
186 {
187  uint64_t ts_start = 1338224400;
188 
189  GENERATE_ACCOUNT(miner_account);
190  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
191  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
192 
193  std::vector<tx_source_entry> sources;
194  std::vector<tx_destination_entry> destinations;
195  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
196 
197  tx_builder builder;
198  builder.step1_init(1 + 1, 0);
199  builder.step2_fill_inputs(miner_account.get_keys(), sources);
200  builder.step3_fill_outputs(destinations);
201  builder.step4_calc_hash();
202  builder.step5_sign(sources);
203 
204  DO_CALLBACK(events, "mark_invalid_tx");
205  events.push_back(builder.m_tx);
206 
207  return true;
208 }
209 
210 bool gen_tx_unlock_time::generate(std::vector<test_event_entry>& events) const
211 {
212  uint64_t ts_start = 1338224400;
213 
214  GENERATE_ACCOUNT(miner_account);
215  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
216  REWIND_BLOCKS_N(events, blk_1, blk_0, miner_account, 10);
217  REWIND_BLOCKS(events, blk_1r, blk_1, miner_account);
218 
219  auto make_tx_with_unlock_time = [&](uint64_t unlock_time) -> transaction
220  {
221  return make_simple_tx_with_unlock_time(events, blk_1, miner_account, miner_account, MK_COINS(1), unlock_time);
222  };
223 
224  std::list<transaction> txs_0;
225 
226  txs_0.push_back(make_tx_with_unlock_time(0));
227  events.push_back(txs_0.back());
228 
229  txs_0.push_back(make_tx_with_unlock_time(get_block_height(blk_1r) - 1));
230  events.push_back(txs_0.back());
231 
232  txs_0.push_back(make_tx_with_unlock_time(get_block_height(blk_1r)));
233  events.push_back(txs_0.back());
234 
235  txs_0.push_back(make_tx_with_unlock_time(get_block_height(blk_1r) + 1));
236  events.push_back(txs_0.back());
237 
238  txs_0.push_back(make_tx_with_unlock_time(get_block_height(blk_1r) + 2));
239  events.push_back(txs_0.back());
240 
241  txs_0.push_back(make_tx_with_unlock_time(ts_start - 1));
242  events.push_back(txs_0.back());
243 
244  txs_0.push_back(make_tx_with_unlock_time(time(0) + 60 * 60));
245  events.push_back(txs_0.back());
246 
247  MAKE_NEXT_BLOCK_TX_LIST(events, blk_2, blk_1r, miner_account, txs_0);
248 
249  return true;
250 }
251 
252 bool gen_tx_input_is_not_txin_to_key::generate(std::vector<test_event_entry>& events) const
253 {
254  uint64_t ts_start = 1338224400;
255 
256  GENERATE_ACCOUNT(miner_account);
257  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
258  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
259 
260  MAKE_NEXT_BLOCK(events, blk_tmp, blk_0r, miner_account);
261  events.pop_back();
262 
263  DO_CALLBACK(events, "mark_invalid_tx");
264  events.push_back(blk_tmp.miner_tx);
265 
266  auto make_tx_with_input = [&](const txin_v& tx_input) -> transaction
267  {
268  std::vector<tx_source_entry> sources;
269  std::vector<tx_destination_entry> destinations;
270  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
271 
272  tx_builder builder;
273  builder.step1_init();
274  builder.m_tx.vin.push_back(tx_input);
275  builder.step3_fill_outputs(destinations);
276  return builder.m_tx;
277  };
278 
279  DO_CALLBACK(events, "mark_invalid_tx");
280  events.push_back(make_tx_with_input(txin_to_script()));
281 
282  DO_CALLBACK(events, "mark_invalid_tx");
283  events.push_back(make_tx_with_input(txin_to_scripthash()));
284 
285  return true;
286 }
287 
288 bool gen_tx_no_inputs_no_outputs::generate(std::vector<test_event_entry>& events) const
289 {
290  uint64_t ts_start = 1338224400;
291 
292  GENERATE_ACCOUNT(miner_account);
293  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
294 
295  tx_builder builder;
296  builder.step1_init();
297 
298  DO_CALLBACK(events, "mark_invalid_tx");
299  events.push_back(builder.m_tx);
300 
301  return true;
302 }
303 
304 bool gen_tx_no_inputs_has_outputs::generate(std::vector<test_event_entry>& events) const
305 {
306  uint64_t ts_start = 1338224400;
307 
308  GENERATE_ACCOUNT(miner_account);
309  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
310 
311  std::vector<tx_source_entry> sources;
312  std::vector<tx_destination_entry> destinations;
313  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
314 
315  tx_builder builder;
316  builder.step1_init();
317  builder.step3_fill_outputs(destinations);
318 
319  DO_CALLBACK(events, "mark_invalid_tx");
320  events.push_back(builder.m_tx);
321 
322  return true;
323 }
324 
325 bool gen_tx_has_inputs_no_outputs::generate(std::vector<test_event_entry>& events) const
326 {
327  uint64_t ts_start = 1338224400;
328 
329  GENERATE_ACCOUNT(miner_account);
330  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
331  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
332 
333  std::vector<tx_source_entry> sources;
334  std::vector<tx_destination_entry> destinations;
335  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
336  destinations.clear();
337 
338  tx_builder builder;
339  builder.step1_init();
340  builder.step2_fill_inputs(miner_account.get_keys(), sources);
341  builder.step3_fill_outputs(destinations);
342  builder.step4_calc_hash();
343  builder.step5_sign(sources);
344 
345  events.push_back(builder.m_tx);
346  MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_account, builder.m_tx);
347 
348  return true;
349 }
350 
351 bool gen_tx_invalid_input_amount::generate(std::vector<test_event_entry>& events) const
352 {
353  uint64_t ts_start = 1338224400;
354 
355  GENERATE_ACCOUNT(miner_account);
356  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
357  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
358 
359  std::vector<tx_source_entry> sources;
360  std::vector<tx_destination_entry> destinations;
361  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
362  sources.front().amount++;
363 
364  tx_builder builder;
365  builder.step1_init();
366  builder.step2_fill_inputs(miner_account.get_keys(), sources);
367  builder.step3_fill_outputs(destinations);
368  builder.step4_calc_hash();
369  builder.step5_sign(sources);
370 
371  DO_CALLBACK(events, "mark_invalid_tx");
372  events.push_back(builder.m_tx);
373 
374  return true;
375 }
376 
377 bool gen_tx_input_wo_key_offsets::generate(std::vector<test_event_entry>& events) const
378 {
379  uint64_t ts_start = 1338224400;
380 
381  GENERATE_ACCOUNT(miner_account);
382  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
383  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
384 
385  std::vector<tx_source_entry> sources;
386  std::vector<tx_destination_entry> destinations;
387  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
388 
389  tx_builder builder;
390  builder.step1_init();
391  builder.step2_fill_inputs(miner_account.get_keys(), sources);
392  builder.step3_fill_outputs(destinations);
393  txin_to_key& in_to_key = boost::get<txin_to_key>(builder.m_tx.vin.front());
394  uint64_t key_offset = in_to_key.key_offsets.front();
395  in_to_key.key_offsets.pop_back();
396  CHECK_AND_ASSERT_MES(in_to_key.key_offsets.empty(), false, "txin contained more than one key_offset");
397  builder.step4_calc_hash();
398  in_to_key.key_offsets.push_back(key_offset);
399  builder.step5_sign(sources);
400  in_to_key.key_offsets.pop_back();
401 
402  DO_CALLBACK(events, "mark_invalid_tx");
403  events.push_back(builder.m_tx);
404 
405  return true;
406 }
407 
408 bool gen_tx_key_offest_points_to_foreign_key::generate(std::vector<test_event_entry>& events) const
409 {
410  uint64_t ts_start = 1338224400;
411 
412  GENERATE_ACCOUNT(miner_account);
413  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
414  MAKE_NEXT_BLOCK(events, blk_1, blk_0, miner_account);
415  REWIND_BLOCKS(events, blk_1r, blk_1, miner_account);
416  MAKE_ACCOUNT(events, alice_account);
417  MAKE_ACCOUNT(events, bob_account);
418  MAKE_TX_LIST_START(events, txs_0, miner_account, bob_account, MK_COINS(15) + 1, blk_1);
419  MAKE_TX_LIST(events, txs_0, miner_account, alice_account, MK_COINS(15) + 1, blk_1);
420  MAKE_NEXT_BLOCK_TX_LIST(events, blk_2, blk_1r, miner_account, txs_0);
421 
422  std::vector<tx_source_entry> sources_bob;
423  std::vector<tx_destination_entry> destinations_bob;
424  fill_tx_sources_and_destinations(events, blk_2, bob_account, miner_account, MK_COINS(15) + 1 - TESTS_DEFAULT_FEE, TESTS_DEFAULT_FEE, 0, sources_bob, destinations_bob);
425 
426  std::vector<tx_source_entry> sources_alice;
427  std::vector<tx_destination_entry> destinations_alice;
428  fill_tx_sources_and_destinations(events, blk_2, alice_account, miner_account, MK_COINS(15) + 1 - TESTS_DEFAULT_FEE, TESTS_DEFAULT_FEE, 0, sources_alice, destinations_alice);
429 
430  tx_builder builder;
431  builder.step1_init();
432  builder.step2_fill_inputs(bob_account.get_keys(), sources_bob);
433  txin_to_key& in_to_key = boost::get<txin_to_key>(builder.m_tx.vin.front());
434  in_to_key.key_offsets.front() = sources_alice.front().outputs.front().first;
435  builder.step3_fill_outputs(destinations_bob);
436  builder.step4_calc_hash();
437  builder.step5_sign(sources_bob);
438 
439  DO_CALLBACK(events, "mark_invalid_tx");
440  events.push_back(builder.m_tx);
441 
442  return true;
443 }
444 
445 bool gen_tx_sender_key_offest_not_exist::generate(std::vector<test_event_entry>& events) const
446 {
447  uint64_t ts_start = 1338224400;
448 
449  GENERATE_ACCOUNT(miner_account);
450  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
451  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
452 
453  std::vector<tx_source_entry> sources;
454  std::vector<tx_destination_entry> destinations;
455  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
456 
457  tx_builder builder;
458  builder.step1_init();
459  builder.step2_fill_inputs(miner_account.get_keys(), sources);
460  txin_to_key& in_to_key = boost::get<txin_to_key>(builder.m_tx.vin.front());
461  in_to_key.key_offsets.front() = std::numeric_limits<uint64_t>::max();
462  builder.step3_fill_outputs(destinations);
463  builder.step4_calc_hash();
464  builder.step5_sign(sources);
465 
466  DO_CALLBACK(events, "mark_invalid_tx");
467  events.push_back(builder.m_tx);
468 
469  return true;
470 }
471 
472 bool gen_tx_mixed_key_offest_not_exist::generate(std::vector<test_event_entry>& events) const
473 {
474  uint64_t ts_start = 1338224400;
475 
476  GENERATE_ACCOUNT(miner_account);
477  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
478  MAKE_NEXT_BLOCK(events, blk_1, blk_0, miner_account);
479  REWIND_BLOCKS(events, blk_1r, blk_1, miner_account);
480  MAKE_ACCOUNT(events, alice_account);
481  MAKE_ACCOUNT(events, bob_account);
482  MAKE_TX_LIST_START(events, txs_0, miner_account, bob_account, MK_COINS(1) + TESTS_DEFAULT_FEE, blk_1);
483  MAKE_TX_LIST(events, txs_0, miner_account, alice_account, MK_COINS(1) + TESTS_DEFAULT_FEE, blk_1);
484  MAKE_NEXT_BLOCK_TX_LIST(events, blk_2, blk_1r, miner_account, txs_0);
485 
486  std::vector<tx_source_entry> sources;
487  std::vector<tx_destination_entry> destinations;
488  fill_tx_sources_and_destinations(events, blk_2, bob_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 1, sources, destinations);
489 
490  sources.front().outputs[(sources.front().real_output + 1) % 2].first = std::numeric_limits<uint64_t>::max();
491 
492  tx_builder builder;
493  builder.step1_init();
494  builder.step2_fill_inputs(bob_account.get_keys(), sources);
495  builder.step3_fill_outputs(destinations);
496  builder.step4_calc_hash();
497  builder.step5_sign(sources);
498 
499  DO_CALLBACK(events, "mark_invalid_tx");
500  events.push_back(builder.m_tx);
501 
502  return true;
503 }
504 
505 bool gen_tx_key_image_not_derive_from_tx_key::generate(std::vector<test_event_entry>& events) const
506 {
507  uint64_t ts_start = 1338224400;
508 
509  GENERATE_ACCOUNT(miner_account);
510  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
511  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
512 
513  std::vector<tx_source_entry> sources;
514  std::vector<tx_destination_entry> destinations;
515  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
516 
517  tx_builder builder;
518  builder.step1_init();
519  builder.step2_fill_inputs(miner_account.get_keys(), sources);
520 
521  txin_to_key& in_to_key = boost::get<txin_to_key>(builder.m_tx.vin.front());
522  keypair kp = keypair::generate(hw::get_device("default"));
523  key_image another_ki;
524  crypto::generate_key_image(kp.pub, kp.sec, another_ki);
525  in_to_key.k_image = another_ki;
526 
527  builder.step3_fill_outputs(destinations);
528  builder.step4_calc_hash();
529 
530  // Tx with invalid key image can't be subscribed, so create empty signature
531  builder.m_tx.signatures.resize(1);
532  builder.m_tx.signatures[0].resize(1);
533  builder.m_tx.signatures[0][0] = boost::value_initialized<crypto::signature>();
534 
535  DO_CALLBACK(events, "mark_invalid_tx");
536  events.push_back(builder.m_tx);
537 
538  return true;
539 }
540 
541 bool gen_tx_key_image_is_invalid::generate(std::vector<test_event_entry>& events) const
542 {
543  uint64_t ts_start = 1338224400;
544 
545  GENERATE_ACCOUNT(miner_account);
546  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
547  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
548 
549  std::vector<tx_source_entry> sources;
550  std::vector<tx_destination_entry> destinations;
551  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
552 
553  tx_builder builder;
554  builder.step1_init();
555  builder.step2_fill_inputs(miner_account.get_keys(), sources);
556 
557  txin_to_key& in_to_key = boost::get<txin_to_key>(builder.m_tx.vin.front());
558  in_to_key.k_image = generate_invalid_key_image();
559 
560  builder.step3_fill_outputs(destinations);
561  builder.step4_calc_hash();
562 
563  // Tx with invalid key image can't be subscribed, so create empty signature
564  builder.m_tx.signatures.resize(1);
565  builder.m_tx.signatures[0].resize(1);
566  builder.m_tx.signatures[0][0] = boost::value_initialized<crypto::signature>();
567 
568  DO_CALLBACK(events, "mark_invalid_tx");
569  events.push_back(builder.m_tx);
570 
571  return true;
572 }
573 
574 bool gen_tx_check_input_unlock_time::generate(std::vector<test_event_entry>& events) const
575 {
576  static const size_t tests_count = 6;
577 
578  uint64_t ts_start = 1338224400;
579 
580  GENERATE_ACCOUNT(miner_account);
581  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
582  REWIND_BLOCKS_N(events, blk_1, blk_0, miner_account, tests_count - 1);
583  REWIND_BLOCKS(events, blk_1r, blk_1, miner_account);
584 
585  std::array<account_base, tests_count> accounts;
586  for (size_t i = 0; i < tests_count; ++i)
587  {
588  MAKE_ACCOUNT(events, acc);
589  accounts[i] = acc;
590  }
591 
592  std::list<transaction> txs_0;
593  auto make_tx_to_acc = [&](size_t acc_idx, uint64_t unlock_time)
594  {
595  txs_0.push_back(make_simple_tx_with_unlock_time(events, blk_1, miner_account, accounts[acc_idx],
596  MK_COINS(1) + TESTS_DEFAULT_FEE, unlock_time));
597  events.push_back(txs_0.back());
598  };
599 
600  uint64_t blk_3_height = get_block_height(blk_1r) + 2;
601  make_tx_to_acc(0, 0);
602  make_tx_to_acc(1, blk_3_height - 1);
603  make_tx_to_acc(2, blk_3_height);
604  make_tx_to_acc(3, blk_3_height + 1);
605  make_tx_to_acc(4, time(0) - 1);
606  make_tx_to_acc(5, time(0) + 60 * 60);
607  MAKE_NEXT_BLOCK_TX_LIST(events, blk_2, blk_1r, miner_account, txs_0);
608 
609  std::list<transaction> txs_1;
610  auto make_tx_from_acc = [&](size_t acc_idx, bool invalid)
611  {
612  transaction tx = make_simple_tx_with_unlock_time(events, blk_2, accounts[acc_idx], miner_account, MK_COINS(1), 0);
613  if (invalid)
614  {
615  DO_CALLBACK(events, "mark_invalid_tx");
616  }
617  else
618  {
619  txs_1.push_back(tx);
620  }
621  events.push_back(tx);
622  };
623 
624  make_tx_from_acc(0, false);
625  make_tx_from_acc(1, false);
626  make_tx_from_acc(2, false);
627  make_tx_from_acc(3, true);
628  make_tx_from_acc(4, false);
629  make_tx_from_acc(5, true);
630  MAKE_NEXT_BLOCK_TX_LIST(events, blk_3, blk_2, miner_account, txs_1);
631 
632  return true;
633 }
634 
635 bool gen_tx_txout_to_key_has_invalid_key::generate(std::vector<test_event_entry>& events) const
636 {
637  uint64_t ts_start = 1338224400;
638 
639  GENERATE_ACCOUNT(miner_account);
640  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
641  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
642 
643  std::vector<tx_source_entry> sources;
644  std::vector<tx_destination_entry> destinations;
645  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
646 
647  tx_builder builder;
648  builder.step1_init();
649  builder.step2_fill_inputs(miner_account.get_keys(), sources);
650  builder.step3_fill_outputs(destinations);
651 
652  txout_to_key& out_to_key = boost::get<txout_to_key>(builder.m_tx.vout.front().target);
653  out_to_key.key = generate_invalid_pub_key();
654 
655  builder.step4_calc_hash();
656  builder.step5_sign(sources);
657 
658  DO_CALLBACK(events, "mark_invalid_tx");
659  events.push_back(builder.m_tx);
660 
661  return true;
662 }
663 
664 bool gen_tx_output_with_zero_amount::generate(std::vector<test_event_entry>& events) const
665 {
666  uint64_t ts_start = 1338224400;
667 
668  GENERATE_ACCOUNT(miner_account);
669  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
670  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
671 
672  std::vector<tx_source_entry> sources;
673  std::vector<tx_destination_entry> destinations;
674  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
675 
676  tx_builder builder;
677  builder.step1_init();
678  builder.step2_fill_inputs(miner_account.get_keys(), sources);
679  builder.step3_fill_outputs(destinations);
680 
681  builder.m_tx.vout.front().amount = 0;
682 
683  builder.step4_calc_hash();
684  builder.step5_sign(sources);
685 
686  DO_CALLBACK(events, "mark_invalid_tx");
687  events.push_back(builder.m_tx);
688 
689  return true;
690 }
691 
692 bool gen_tx_output_is_not_txout_to_key::generate(std::vector<test_event_entry>& events) const
693 {
694  uint64_t ts_start = 1338224400;
695 
696  GENERATE_ACCOUNT(miner_account);
697  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
698  REWIND_BLOCKS(events, blk_0r, blk_0, miner_account);
699 
700  std::vector<tx_source_entry> sources;
701  std::vector<tx_destination_entry> destinations;
702  fill_tx_sources_and_destinations(events, blk_0, miner_account, miner_account, MK_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
703 
704  tx_builder builder;
705  builder.step1_init();
706  builder.step2_fill_inputs(miner_account.get_keys(), sources);
707 
708  builder.m_tx.vout.push_back(tx_out());
709  builder.m_tx.vout.back().amount = 1;
710  builder.m_tx.vout.back().target = txout_to_script();
711 
712  builder.step4_calc_hash();
713  builder.step5_sign(sources);
714 
715  DO_CALLBACK(events, "mark_invalid_tx");
716  events.push_back(builder.m_tx);
717 
718  builder.step1_init();
719  builder.step2_fill_inputs(miner_account.get_keys(), sources);
720 
721  builder.m_tx.vout.push_back(tx_out());
722  builder.m_tx.vout.back().amount = 1;
723  builder.m_tx.vout.back().target = txout_to_scripthash();
724 
725  builder.step4_calc_hash();
726  builder.step5_sign(sources);
727 
728  DO_CALLBACK(events, "mark_invalid_tx");
729  events.push_back(builder.m_tx);
730 
731  return true;
732 }
733 
734 bool gen_tx_signatures_are_invalid::generate(std::vector<test_event_entry>& events) const
735 {
736  uint64_t ts_start = 1338224400;
737 
738  GENERATE_ACCOUNT(miner_account);
739  MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
740  MAKE_NEXT_BLOCK(events, blk_1, blk_0, miner_account);
741  REWIND_BLOCKS(events, blk_1r, blk_1, miner_account);
742  MAKE_ACCOUNT(events, alice_account);
743  MAKE_ACCOUNT(events, bob_account);
744  MAKE_TX_LIST_START(events, txs_0, miner_account, bob_account, MK_COINS(1) + TESTS_DEFAULT_FEE, blk_1);
745  MAKE_TX_LIST(events, txs_0, miner_account, alice_account, MK_COINS(1) + TESTS_DEFAULT_FEE, blk_1);
746  MAKE_NEXT_BLOCK_TX_LIST(events, blk_2, blk_1r, miner_account, txs_0);
747 
748  MAKE_TX(events, tx_0, miner_account, miner_account, MK_COINS(60), blk_2);
749  events.pop_back();
750 
751  MAKE_TX_MIX(events, tx_1, bob_account, miner_account, MK_COINS(1), 1, blk_2);
752  events.pop_back();
753 
754  // Tx with nmix = 0 without signatures
755  DO_CALLBACK(events, "mark_invalid_tx");
756  blobdata sr_tx = t_serializable_object_to_blob(static_cast<transaction_prefix>(tx_0));
757  events.push_back(serialized_transaction(sr_tx));
758 
759  // Tx with nmix = 0 have a few inputs, and not enough signatures
760  DO_CALLBACK(events, "mark_invalid_tx");
761  sr_tx = t_serializable_object_to_blob(tx_0);
762  sr_tx.resize(sr_tx.size() - sizeof(crypto::signature));
763  events.push_back(serialized_transaction(sr_tx));
764 
765  // Tx with nmix = 0 have a few inputs, and too many signatures
766  DO_CALLBACK(events, "mark_invalid_tx");
767  sr_tx = t_serializable_object_to_blob(tx_0);
768  sr_tx.insert(sr_tx.end(), sr_tx.end() - sizeof(crypto::signature), sr_tx.end());
769  events.push_back(serialized_transaction(sr_tx));
770 
771  // Tx with nmix = 1 without signatures
772  DO_CALLBACK(events, "mark_invalid_tx");
773  sr_tx = t_serializable_object_to_blob(static_cast<transaction_prefix>(tx_1));
774  events.push_back(serialized_transaction(sr_tx));
775 
776  // Tx with nmix = 1 have not enough signatures
777  DO_CALLBACK(events, "mark_invalid_tx");
778  sr_tx = t_serializable_object_to_blob(tx_1);
779  sr_tx.resize(sr_tx.size() - sizeof(crypto::signature));
780  events.push_back(serialized_transaction(sr_tx));
781 
782  // Tx with nmix = 1 have too many signatures
783  DO_CALLBACK(events, "mark_invalid_tx");
784  sr_tx = t_serializable_object_to_blob(tx_1);
785  sr_tx.insert(sr_tx.end(), sr_tx.end() - sizeof(crypto::signature), sr_tx.end());
786  events.push_back(serialized_transaction(sr_tx));
787 
788  return true;
789 }
bool generate(std::vector< test_event_entry > &events) const
#define MAKE_NEXT_BLOCK_TX1(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TX1)
Definition: chaingen.h:849
std::vector< std::string > keypair
crypto::public_key real_out_tx_key
bool generate(std::vector< test_event_entry > &events) const
POD_CLASS key_derivation
Definition: crypto.h:98
bool generate(std::vector< test_event_entry > &events) const
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
void fill_tx_sources_and_destinations(const std::vector< test_event_entry > &events, const block &blk_head, const cryptonote::account_base &from, const cryptonote::account_public_address &to, uint64_t amount, uint64_t fee, size_t nmix, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations)
Definition: chaingen.cpp:775
bool generate(std::vector< test_event_entry > &events) const
const char * key
Definition: hmac_keccak.cpp:39
#define REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT)
Definition: chaingen.h:889
crypto namespace.
Definition: crypto.cpp:58
STL namespace.
#define MAKE_NEXT_BLOCK(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC)
Definition: chaingen.h:839
std::vector< uint64_t > key_offsets
#define TESTS_DEFAULT_FEE
Definition: chaingen.h:1061
bool generate(std::vector< test_event_entry > &events) const
uint64_t amount
#define MAKE_TX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition: chaingen.h:933
bool generate(std::vector< test_event_entry > &events) const
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
size_t real_output
const account_keys & get_keys() const
Definition: account.cpp:264
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
bool generate(std::vector< test_event_entry > &events) const
time_t time
Definition: blockchain.cpp:93
bool add_tx_pub_key_to_extra(transaction &tx, const crypto::public_key &tx_pub_key)
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition: crypto.h:324
bool generate(std::vector< test_event_entry > &events) const
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)
bool generate(std::vector< test_event_entry > &events) const
#define MAKE_TX_MIX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, NMIX, HEAD)
Definition: chaingen.h:893
std::vector< uint64_t > absolute_output_offsets_to_relative(const std::vector< uint64_t > &off)
void generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const secret_key &sec, std::size_t sec_index, signature *sig)
Definition: crypto.h:327
device & get_device(const std::string &device_descriptor)
Definition: device.cpp:95
#define MAKE_GENESIS_BLOCK(VEC_EVENTS, BLK_NAME, MINER_ACC, TS)
Definition: chaingen.h:833
unsigned __int64 uint64_t
Definition: stdint.h:136
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
uint64_t amount
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
bool generate(std::vector< test_event_entry > &events) const
#define MAKE_TX_LIST_START(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition: chaingen.h:935
bool generate(std::vector< test_event_entry > &events) const
POD_CLASS public_key
Definition: crypto.h:76
version
Supported socks variants.
Definition: socks.h:57
bool generate(std::vector< test_event_entry > &events) const
account_public_address addr
std::string blobdata
Definition: blobdatatype.h:39
account_public_address m_account_address
Definition: account.h:43
bool generate(std::vector< test_event_entry > &events) const
POD_CLASS signature
Definition: crypto.h:108
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
bool generate(std::vector< test_event_entry > &events) const
#define MAKE_ACCOUNT(VEC_EVENTS, account)
Definition: chaingen.h:815
crypto::public_key key
#define REWIND_BLOCKS(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC)
Definition: chaingen.h:890
std::vector< crypto::public_key > real_out_additional_tx_keys
POD_CLASS key_image
Definition: crypto.h:102
size_t real_output_in_tx_index
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
Definition: crypto.h:275
crypto::key_image k_image
bool check_key(const public_key &key)
Definition: crypto.h:256
std::vector< output_entry > outputs
bool generate(std::vector< test_event_entry > &events) const
serialized_object< cryptonote::transaction > serialized_transaction
Definition: chaingen.h:108
#define MAKE_TX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, HEAD)
Definition: chaingen.h:903
POD_CLASS hash
Definition: hash.h:50
bool generate(std::vector< test_event_entry > &events) const
#define MK_COINS(amount)
Definition: chaingen.h:1060
std::pair< uint64_t, rct::ctkey > output_entry
#define GENERATE_ACCOUNT(account)
Definition: chaingen.h:801
bool generate(std::vector< test_event_entry > &events) const
#define DO_CALLBACK(VEC_EVENTS, CB_NAME)
Definition: chaingen.h:820
#define MAKE_NEXT_BLOCK_TX_LIST(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST)
Definition: chaingen.h:867
bool generate(std::vector< test_event_entry > &events) const
uint64_t get_block_height(const block &b)