Electroneum
trezor_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2018, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
30 
31 #include "include_base_utils.h"
35 #include "misc_language.h"
36 #include "string_tools.h"
37 
38 using namespace cryptonote;
39 
40 #include <boost/regex.hpp>
41 #include "common/util.h"
42 #include "common/command_line.h"
43 #include "trezor_tests.h"
44 #include "tools.h"
45 #include "device/device_cold.hpp"
47 
48 
49 namespace po = boost::program_options;
50 
51 namespace
52 {
53  const command_line::arg_descriptor<std::string> arg_filter = { "filter", "Regular expression filter for which tests to run" };
54  const command_line::arg_descriptor<bool> arg_generate_and_play_test_data = {"generate_and_play_test_data", ""};
55  const command_line::arg_descriptor<std::string> arg_trezor_path = {"trezor_path", "Path to the trezor device to use, has to support debug link", ""};
56  const command_line::arg_descriptor<bool> arg_heavy_tests = {"heavy_tests", "Runs expensive tests (volume tests with real device)", false};
57  const command_line::arg_descriptor<std::string> arg_chain_path = {"chain_path", "Path to the serialized blockchain, speeds up testing", ""};
58  const command_line::arg_descriptor<bool> arg_fix_chain = {"fix_chain", "If chain_patch is given and file cannot be used, it is ignored and overwriten", false};
59 }
60 
61 #define HW_TREZOR_NAME "Trezor"
62 #define TREZOR_ACCOUNT_ORDERING &m_miner_account, &m_alice_account, &m_bob_account, &m_eve_account
63 #define TREZOR_COMMON_TEST_CASE(genclass, CORE, BASE) do { \
64  rollback_chain(CORE, BASE.head_block()); \
65  { \
66  genclass ctest; \
67  BASE.fork(ctest); \
68  GENERATE_AND_PLAY_INSTANCE(genclass, ctest, *(CORE)); \
69  } \
70 } while(0)
71 
72 #define TREZOR_SETUP_CHAIN(NAME) do { \
73  ++tests_count; \
74  try { \
75  setup_chain(core, trezor_base, chain_path, fix_chain, vm_core); \
76  } catch (const std::exception& ex) { \
77  failed_tests.emplace_back("gen_trezor_base " #NAME); \
78  } \
79 } while(0)
80 
81 
82 static device_trezor_test *trezor_device = nullptr;
83 static device_trezor_test *ensure_trezor_test_device();
84 static void rollback_chain(cryptonote::core * core, const cryptonote::block & head);
85 static void setup_chain(cryptonote::core * core, gen_trezor_base & trezor_base, std::string chain_path, bool fix_chain, const po::variables_map & vm_core);
86 
87 static long get_env_long(const char * flag_name, boost::optional<long> def = boost::none){
88  const char *env_data = getenv(flag_name);
89  return env_data ? atol(env_data) : (def ? def.get() : 0);
90 }
91 
92 int main(int argc, char* argv[])
93 {
94  TRY_ENTRY();
97 
98  //set up logging options
99  mlog_configure(mlog_get_default_log_path("trezor_tests.log"), true);
101 
102  po::options_description desc_options("Allowed options");
104  command_line::add_arg(desc_options, arg_filter);
105  command_line::add_arg(desc_options, arg_trezor_path);
106  command_line::add_arg(desc_options, arg_heavy_tests);
107  command_line::add_arg(desc_options, arg_chain_path);
108  command_line::add_arg(desc_options, arg_fix_chain);
109 
110  po::variables_map vm;
111  bool r = command_line::handle_error_helper(desc_options, [&]()
112  {
113  po::store(po::parse_command_line(argc, argv, desc_options), vm);
114  po::notify(vm);
115  return true;
116  });
117  if (!r)
118  return 1;
119 
121  {
122  std::cout << desc_options << std::endl;
123  return 0;
124  }
125 
126  const std::string filter = tools::glob_to_regex(command_line::get_arg(vm, arg_filter));
127  boost::smatch match;
128 
129  size_t tests_count = 0;
130  std::vector<std::string> failed_tests;
131  std::string trezor_path = command_line::get_arg(vm, arg_trezor_path);
132  std::string chain_path = command_line::get_arg(vm, arg_chain_path);
133  const bool heavy_tests = command_line::get_arg(vm, arg_heavy_tests);
134  const bool fix_chain = command_line::get_arg(vm, arg_fix_chain);
135 
136  hw::register_device(HW_TREZOR_NAME, ensure_trezor_test_device()); // shim device for call tracking
137 
138  // Bootstrapping common chain & accounts
139  const uint8_t initial_hf = (uint8_t)get_env_long("TEST_MIN_HF", 11);
140  const uint8_t max_hf = (uint8_t)get_env_long("TEST_MAX_HF", 11);
141  MINFO("Test versions " << ELECTRONEUM_RELEASE_NAME << "' (v" << ELECTRONEUM_VERSION_FULL << ")");
142  MINFO("Testing hardforks [" << (int)initial_hf << ", " << (int)max_hf << "]");
143 
144  cryptonote::core core_obj(nullptr);
145  cryptonote::core * const core = &core_obj;
146  std::shared_ptr<mock_daemon> daemon = nullptr;
147 
148  gen_trezor_base trezor_base;
149  trezor_base.setup_args(trezor_path, heavy_tests);
150  trezor_base.set_hard_fork(initial_hf);
151 
152  // Arguments for core & daemon
153  po::variables_map vm_core;
154  po::options_description desc_params_core("Core");
155  mock_daemon::init_options(desc_params_core);
156  tools::options::build_options(vm_core, desc_params_core);
158 
159  // Transaction tests
160  for(uint8_t hf=initial_hf; hf <= max_hf + 1; ++hf)
161  {
162  if (hf > initial_hf || hf > max_hf)
163  {
164  daemon->stop_and_deinit();
165  daemon = nullptr;
166  trezor_base.daemon(nullptr);
167  if (hf > max_hf)
168  {
169  break;
170  }
171  }
172 
173  MDEBUG("Transaction tests for HF " << (int)hf);
174  trezor_base.set_hard_fork(hf);
176 
177  daemon = std::make_shared<mock_daemon>(core, vm_core);
178  CHECK_AND_ASSERT_THROW_MES(daemon->nettype() == trezor_base.nettype(), "Serialized chain network type does not match");
179 
180  daemon->try_init_and_run();
181  trezor_base.daemon(daemon);
182 
183  // Hard-fork independent tests
184  if (hf == initial_hf)
185  {
189  }
190 
203  }
204 
205  if (trezor_base.heavy_tests())
206  {
208  }
209 
210  core->deinit();
211  el::Level level = (failed_tests.empty() ? el::Level::Info : el::Level::Error);
212  MLOG(level, "\nREPORT:");
213  MLOG(level, " Test run: " << tests_count);
214  MLOG(level, " Failures: " << failed_tests.size());
215  if (!failed_tests.empty())
216  {
217  MLOG(level, "FAILED TESTS:");
218  BOOST_FOREACH(auto test_name, failed_tests)
219  {
220  MLOG(level, " " << test_name);
221  }
222  }
223 
224  return failed_tests.empty() ? 0 : 1;
225 
226  CATCH_ENTRY_L0("main", 1);
227 }
228 
229 static void rollback_chain(cryptonote::core * core, const cryptonote::block & head)
230 {
231  CHECK_AND_ASSERT_THROW_MES(core, "Core is null");
232 
233  block popped_block;
234  std::vector<transaction> popped_txs;
235 
236  crypto::hash head_hash = get_block_hash(head), cur_hash{};
237  uint64_t height = get_block_height(head), cur_height=0;
238  MDEBUG("Rollbacking to " << height << " to hash " << head_hash);
239 
240  do {
241  core->get_blockchain_top(cur_height, cur_hash);
242 
243  if (cur_height <= height && head_hash == cur_hash)
244  return;
245 
246  CHECK_AND_ASSERT_THROW_MES(cur_height > height, "Height differs");
247  core->get_blockchain_storage().get_db().pop_block(popped_block, popped_txs);
248  } while(true);
249 }
250 
251 static bool unserialize_chain_from_file(std::vector<test_event_entry>& events, gen_trezor_base &test_base, const std::string& file_path)
252 {
253  TRY_ENTRY();
254  std::ifstream data_file;
255  data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
256  if(data_file.fail())
257  return false;
258  try
259  {
261  test_base.clear();
262 
263  a >> events;
264  a >> test_base;
265  return true;
266  }
267  catch(...)
268  {
269  MWARNING("Chain deserialization failed");
270  return false;
271  }
272  CATCH_ENTRY_L0("unserialize_chain_from_file", false);
273 }
274 
275 static bool serialize_chain_to_file(std::vector<test_event_entry>& events, gen_trezor_base &test_base, const std::string& file_path)
276 {
277  TRY_ENTRY();
278  std::ofstream data_file;
279  data_file.open( file_path, std::ios_base::binary | std::ios_base::out | std::ios::trunc);
280  if(data_file.fail())
281  return false;
282  try
283  {
284 
286  a << events;
287  a << test_base;
288  return !data_file.fail();
289  }
290  catch(...)
291  {
292  MWARNING("Chain deserialization failed");
293  return false;
294  }
295  return false;
296  CATCH_ENTRY_L0("serialize_chain_to_file", false);
297 }
298 
299 template<class t_test_class>
300 static bool init_core_replay_events(std::vector<test_event_entry>& events, cryptonote::core * core, const po::variables_map & vm_core)
301 {
302  // this test needs for it to be so.
304 
305  // Hardforks can be specified in events.
306  v_hardforks_t hardforks;
307  cryptonote::test_options test_options_tmp{nullptr, 0};
308  const cryptonote::test_options * test_options_ = &gto.test_options;
309  if (extract_hard_forks(events, hardforks)){
310  hardforks.push_back(std::make_pair((uint8_t)0, (uint64_t)0)); // terminator
311  test_options_tmp.hard_forks = hardforks.data();
312  test_options_ = &test_options_tmp;
313  }
314 
315  core->deinit();
316  CHECK_AND_ASSERT_THROW_MES(core->init(vm_core, test_options_), "Core init failed");
318 
319  // start with a clean pool
320  std::vector<crypto::hash> pool_txs;
321  CHECK_AND_ASSERT_THROW_MES(core->get_pool_transaction_hashes(pool_txs), "Failed to flush txpool");
323 
324  t_test_class validator;
325  return replay_events_through_core<t_test_class>(*core, events, validator);
326 }
327 
328 static void setup_chain(cryptonote::core * core, gen_trezor_base & trezor_base, std::string chain_path, bool fix_chain, const po::variables_map & vm_core)
329 {
330  std::vector<test_event_entry> events;
331  const bool do_serialize = !chain_path.empty();
332  const bool chain_file_exists = do_serialize && boost::filesystem::exists(chain_path);
333  bool loaded = false;
334  bool generated = false;
335 
336  if (chain_file_exists)
337  {
338  if (!unserialize_chain_from_file(events, trezor_base, chain_path))
339  {
340  MERROR("Failed to deserialize data from file: " << chain_path);
341  if (!fix_chain)
342  {
343  throw std::runtime_error("Chain load error");
344  }
345  } else
346  {
347  trezor_base.load(events);
348  generated = true;
349  loaded = true;
350  }
351  }
352 
353  if (!generated)
354  {
355  try
356  {
357  trezor_base.clear();
358  generated = trezor_base.generate(events);
359 
360  if (generated && !loaded && do_serialize)
361  {
362  trezor_base.update_trackers(events);
363  if (!serialize_chain_to_file(events, trezor_base, chain_path))
364  {
365  MERROR("Failed to serialize data to file: " << chain_path);
366  }
367  }
368  }
370  }
371 
372  trezor_base.fix_hf(events);
373  if (generated && init_core_replay_events<gen_trezor_base>(events, core, vm_core))
374  {
375  MGINFO_GREEN("#TEST-chain-init# Succeeded ");
376  }
377  else
378  {
379  MERROR("#TEST-chain-init# Failed ");
380  throw std::runtime_error("Chain init error");
381  }
382 }
383 
384 static device_trezor_test *ensure_trezor_test_device(){
385  if (!trezor_device) {
386  trezor_device = new device_trezor_test();
387  trezor_device->set_name(HW_TREZOR_NAME);
388  }
389  return trezor_device;
390 }
391 
392 static void add_hforks(std::vector<test_event_entry>& events, const v_hardforks_t& hard_forks)
393 {
394  event_replay_settings repl_set;
395  repl_set.hard_forks = boost::make_optional(hard_forks);
396  events.push_back(repl_set);
397 }
398 
399 static void add_top_hfork(std::vector<test_event_entry>& events, const v_hardforks_t& hard_forks)
400 {
401  event_replay_settings repl_set;
402  v_hardforks_t top_fork;
403  top_fork.push_back(hard_forks.back());
404  repl_set.hard_forks = boost::make_optional(top_fork);
405  events.push_back(repl_set);
406 }
407 
408 static crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td)
409 {
410  std::vector<tx_extra_field> tx_extra_fields;
411  parse_tx_extra(td.m_tx.extra, tx_extra_fields);
412 
413  tx_extra_pub_key pub_key_field;
415  "Public key wasn't found in the transaction extra");
416  const crypto::public_key tx_pub_key = pub_key_field.pub_key;
417  bool two_found = find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 1);
418  if (!two_found) {
419  return tx_pub_key;
420  } else {
421  throw std::runtime_error("Unsupported tx pub resolution");
422  }
423 }
424 
425 static void setup_shim(hw::wallet_shim * shim)
426 {
427  shim->get_tx_pub_key_from_received_outs = &get_tx_pub_key_from_received_outs;
428 }
429 
431 {
432  std::vector<tx_extra_field> tx_extra_fields;
433  parse_tx_extra(ptx.tx.extra, tx_extra_fields); // ok if partially parsed
434  cryptonote::tx_extra_nonce extra_nonce;
435  if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
436  {
437  if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
438  {
439  if (ptx.dests.empty())
440  {
441  MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt");
442  return false;
443  }
444  return hwdev.decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key);
445  }
446  }
447  return false;
448 }
449 
450 static tools::wallet2::tx_construction_data get_construction_data_with_decrypted_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::device &hwdev)
451 {
453  crypto::hash8 payment_id = crypto::null_hash8;
454  if (get_short_payment_id(payment_id, ptx, hwdev))
455  {
456  // Remove encrypted
457  remove_field_from_tx_extra(construction_data.extra, typeid(cryptonote::tx_extra_nonce));
458  // Add decrypted
459  std::string extra_nonce;
460  crypto::hash payment_id = null_hash;
461  memcpy(payment_id.data, info.payment_id.data, 8); // convert short pid to regular
462  memset(payment_id.data + 8, 0, 24); // merely a sanity check
463 
464  set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
465  THROW_WALLET_EXCEPTION_IF(!add_extra_nonce_to_tx_extra(construction_data.extra, extra_nonce),
466  tools::error::wallet_internal_error, "Failed to add payment id to tx extra");
467  MDEBUG("Payment ID: " << payment_id);
468  }
469  return construction_data;
470 }
471 
472 static std::string get_payment_id(const std::vector<uint8_t> &tx_extra)
473 {
474  std::vector<cryptonote::tx_extra_field> tx_extra_fields;
475  cryptonote::parse_tx_extra(tx_extra, tx_extra_fields); // ok if partially parsed
476  cryptonote::tx_extra_nonce extra_nonce;
477 
478  ::crypto::hash payment_id{};
479  if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
480  {
481  ::crypto::hash8 payment_id8{};
483  {
484  crypto::hash payment_id = crypto::null_hash;
485  memcpy(payment_id.data, payment_id8.data, 8); // convert short pid to regular
486  memset(payment_id.data + 8, 0, 24); // merely a sanity chec
487  return std::string(payment_id.data, 32);
488  }
489  else if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
490  {
491  return std::string(payment_id.data, 32);
492  }
493  }
494  return std::string();
495 }
496 
497 static crypto::hash8 to_short_payment_id(const std::string & payment_id)
498 {
499  crypto::hash8 payment_id_short;
500  CHECK_AND_ASSERT_THROW_MES(payment_id.size() == 8, "Invalid argument");
501  memcpy(payment_id_short.data, payment_id.data(), 8);
502  return payment_id_short;
503 }
504 
505 static crypto::hash to_long_payment_id(const std::string & payment_id)
506 {
507  crypto::hash payment_id_long;
508  CHECK_AND_ASSERT_THROW_MES(payment_id.size() == 32, "Invalid argument");
509  memcpy(payment_id_long.data, payment_id.data(), 32);
510  return payment_id_long;
511 }
512 
513 static std::vector<uint8_t> build_payment_id_extra(const std::string & payment_id)
514 {
515  std::vector<uint8_t> res;
516 
517  if (payment_id.size() == 8) {
518  std::string extra_nonce;
519  crypto::hash payment_id = null_hash;
520  memcpy(payment_id.data, info.payment_id.data, 8); // convert short pid to regular
521  memset(payment_id.data + 8, 0, 24); // merely a sanity check
522 
523  set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
525  tools::error::wallet_internal_error, "Failed to add payment id to tx extra");
526  } else if (payment_id.size() == 32){
527  std::string extra_nonce;
528  set_payment_id_to_tx_extra_nonce(extra_nonce, to_long_payment_id(payment_id));
530  tools::error::wallet_internal_error, "Failed to add payment id to tx extra");
531  }
532 
533  return res;
534 }
535 
536 static cryptonote::address_parse_info init_addr_parse_info(cryptonote::account_public_address &addr, bool is_sub=false, boost::optional<crypto::hash8> payment_id = boost::none)
537 {
539  res.address = addr;
540  res.is_subaddress = is_sub;
541  if (payment_id){
542  res.has_payment_id = true;
543  res.payment_id = payment_id.get();
544  } else {
545  res.has_payment_id = false;
546  }
547  return res;
548 }
549 
550 static void expand_tsx(cryptonote::transaction &tx)
551 {
552  auto & rv = tx.rct_signatures;
553  if (rv.type == rct::RCTTypeFull)
554  {
555  rv.p.MGs.resize(1);
556  rv.p.MGs[0].II.resize(tx.vin.size());
557  for (size_t n = 0; n < tx.vin.size(); ++n)
558  rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
559  }
560  else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2)
561  {
562  CHECK_AND_ASSERT_THROW_MES(rv.p.MGs.size() == tx.vin.size(), "Bad MGs size");
563  for (size_t n = 0; n < tx.vin.size(); ++n)
564  {
565  rv.p.MGs[n].II.resize(1);
566  rv.p.MGs[n].II[0] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
567  }
568  }
569 }
570 
571 static std::vector<tools::wallet2*> vct_wallets(tools::wallet2* w1=nullptr, tools::wallet2* w2=nullptr, tools::wallet2* w3=nullptr, tools::wallet2* w4=nullptr, tools::wallet2* w5=nullptr)
572 {
573  std::vector<tools::wallet2*> res;
574  if (w1)
575  res.push_back(w1);
576  if (w2)
577  res.push_back(w2);
578  if (w3)
579  res.push_back(w3);
580  if (w4)
581  res.push_back(w4);
582  if (w5)
583  res.push_back(w5);
584  return res;
585 }
586 
587 static uint64_t get_available_funds(tools::wallet2* wallet, uint32_t account=0)
588 {
590  wallet->get_transfers(transfers);
591  uint64_t sum = 0;
592  for(const auto & cur : transfers)
593  {
594  sum += !cur.m_spent && cur.m_subaddr_index.major == account ? cur.amount() : 0;
595  }
596  return sum;
597 }
598 
599 // gen_trezor_base
600 const uint64_t gen_trezor_base::m_ts_start = 1397862000; // As default wallet timestamp is 1397516400
601 const uint64_t gen_trezor_base::m_wallet_ts = m_ts_start - 60*60*24*4;
602 const std::string gen_trezor_base::m_device_name = "Trezor:udp";
603 const std::string gen_trezor_base::m_master_seed_str = "14821d0bc5659b24cafbc889dc4fc60785ee08b65d71c525f81eeaba4f3a570f";
604 const std::string gen_trezor_base::m_device_seed = "permit universe parent weapon amused modify essay borrow tobacco budget walnut lunch consider gallery ride amazing frog forget treat market chapter velvet useless topple";
605 const std::string gen_trezor_base::m_alice_spend_private = m_master_seed_str;
606 const std::string gen_trezor_base::m_alice_view_private = "a6ccd4ac344a295d1387f8d18c81bdd394f1845de84188e204514ef9370fd403";
607 
609  m_rct_config = {rct::RangeProofPaddedBulletproof, 1};
610  m_test_get_tx_key = true;
611  m_network_type = cryptonote::TESTNET;
612 }
613 
615  m_generator(other.m_generator), m_bt(other.m_bt), m_miner_account(other.m_miner_account),
616  m_bob_account(other.m_bob_account), m_alice_account(other.m_alice_account), m_eve_account(other.m_eve_account),
617  m_hard_forks(other.m_hard_forks), m_trezor(other.m_trezor), m_rct_config(other.m_rct_config), m_top_hard_fork(other.m_top_hard_fork),
618  m_heavy_tests(other.m_heavy_tests), m_test_get_tx_key(other.m_test_get_tx_key), m_live_refresh_enabled(other.m_live_refresh_enabled),
619  m_network_type(other.m_network_type), m_daemon(other.m_daemon)
620 {
621 
622 }
623 
624 void gen_trezor_base::setup_args(const std::string & trezor_path, bool heavy_tests)
625 {
626  m_trezor_path = trezor_path.empty() ? m_device_name : std::string("Trezor:") + trezor_path;
628 }
629 
631 {
633  auto trezor = dynamic_cast<device_trezor_test *>(&hwdev);
634  CHECK_AND_ASSERT_THROW_MES(trezor, "Dynamic cast failed");
635 
636  trezor->setup_for_tests(m_trezor_path, m_device_seed, m_network_type);
637  m_trezor = trezor;
638 }
639 
641 {
642  other.m_generator = m_generator;
643  other.m_bt = m_bt;
645  other.m_daemon = m_daemon;
646  other.m_events = m_events;
647  other.m_head = m_head;
648  other.m_hard_forks = m_hard_forks;
652  other.m_rct_config = m_rct_config;
655 
660  other.m_trezor = m_trezor;
661 }
662 
664 {
666  m_bt = block_tracker();
667  m_events.clear();
668  m_hard_forks.clear();
669  m_trezor = nullptr;
670 }
671 
672 void gen_trezor_base::add_shared_events(std::vector<test_event_entry>& events)
673 {
674  events.reserve(m_events.size());
675  for(const test_event_entry & c : m_events){
676  events.push_back(c);
677  }
678 }
679 
681 {
684 
685  crypto::secret_key master_seed{};
687 
688  m_alice_account.generate(master_seed, true);
690 }
691 
693 {
694  auto dev_trezor = dynamic_cast<::hw::trezor::device_trezor*>(m_trezor);
695  CHECK_AND_ASSERT_THROW_MES(dev_trezor, "Could not cast to device_trezor");
696 
697  dev_trezor->set_live_refresh_enabled(m_live_refresh_enabled);
698 }
699 
700 bool gen_trezor_base::generate(std::vector<test_event_entry>& events)
701 {
702  init_fields();
703  setup_trezor();
704 
705  m_live_refresh_enabled = false;
707 
710 
711  // Events, custom genesis so it matches wallet genesis
712  auto & generator = m_generator; // macro shortcut
713 
714  cryptonote::block blk_gen;
715  std::vector<size_t> block_weights;
717  events.push_back(blk_gen);
718  generator.add_block(blk_gen, 0, block_weights, 0);
719 
720  // First event has to be the genesis block
726  for(cryptonote::account_base * ac : accounts){
727  events.push_back(*ac);
728  }
729 
730  // Another block with predefined timestamp.
731  // Carefully set reward and already generated coins so it passes miner_tx check.
732  cryptonote::block blk_0;
733  {
734  std::list<cryptonote::transaction> tx_list;
735  const crypto::hash prev_id = get_block_hash(blk_gen);
736  const uint64_t already_generated_coins = generator.get_already_generated_coins(prev_id);
737  block_weights.clear();
738  generator.get_last_n_block_weights(block_weights, prev_id, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
739  generator.construct_block(blk_0, 1, prev_id, m_miner_account, m_ts_start, already_generated_coins, block_weights, tx_list);
740  }
741 
742  events.push_back(blk_0);
743  MDEBUG("Gen+1 block has time: " << blk_0.timestamp << " blid: " << get_block_hash(blk_0));
744 
745  // Generate some spendable funds on the Miner account
746  REWIND_BLOCKS_N(events, blk_3, blk_0, m_miner_account, 40);
747 
748  // Rewind so the miners funds are unlocked for initial transactions.
749  REWIND_BLOCKS(events, blk_3r, blk_3, m_miner_account);
750 
751  // Non-rct transactions Miner -> Bob
752  MAKE_TX_LIST_START(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(10), blk_3);
753  MAKE_TX_LIST(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(7), blk_3);
754  MAKE_TX_LIST(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(7), blk_3);
755  MAKE_TX_LIST(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(14), blk_3);
756  MAKE_TX_LIST(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(20), blk_3);
757  MAKE_TX_LIST(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(2), blk_3);
758  MAKE_TX_LIST(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(2), blk_3);
759  MAKE_TX_LIST(events, txs_blk_4, m_miner_account, m_alice_account, MK_COINS(5), blk_3);
760  MAKE_NEXT_BLOCK_TX_LIST(events, blk_4, blk_3r, m_miner_account, txs_blk_4);
761  REWIND_BLOCKS(events, blk_4r, blk_4, m_miner_account); // rewind to unlock
762 
763  // Hard fork to bulletproofs version, v9.
764  const uint8_t CUR_HF = 9;
765  auto hardfork_height = num_blocks(events); // next block is v9
766  ADD_HARDFORK(m_hard_forks, CUR_HF, hardfork_height);
767  add_hforks(events, m_hard_forks);
768  MDEBUG("Hardfork height: " << hardfork_height << " at block: " << get_block_hash(blk_4r));
769 
770  // RCT transactions, wallets have to be used, wallet init
771  m_wl_alice.reset(new tools::wallet2(m_network_type, 1, true));
772  m_wl_bob.reset(new tools::wallet2(m_network_type, 1, true));
775 
776  auto addr_alice_sub_0_1 = m_wl_alice->get_subaddress({0, 1});
777  auto addr_alice_sub_0_2 = m_wl_alice->get_subaddress({0, 2});
778  auto addr_alice_sub_0_3 = m_wl_alice->get_subaddress({0, 3});
779  auto addr_alice_sub_0_4 = m_wl_alice->get_subaddress({0, 4});
780  auto addr_alice_sub_0_5 = m_wl_alice->get_subaddress({0, 5});
781  auto addr_alice_sub_1_0 = m_wl_alice->get_subaddress({1, 0});
782  auto addr_alice_sub_1_1 = m_wl_alice->get_subaddress({1, 1});
783  auto addr_alice_sub_1_2 = m_wl_alice->get_subaddress({1, 2});
784 
785  // Miner -> Bob, RCT funds
786  MAKE_TX_LIST_START_RCT(events, txs_blk_5, m_miner_account, m_alice_account, MK_COINS(50), 10, blk_4);
787 
788  const size_t target_rct = m_heavy_tests ? 105 : 15;
789  for(size_t i = 0; i < target_rct; ++i)
790  {
791  MAKE_TX_MIX_LIST_RCT(events, txs_blk_5, m_miner_account, m_alice_account, MK_COINS(1) >> 2, 10, blk_4);
792  }
793 
794  // Sub-address destinations
795  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts(addr_alice_sub_0_1, true, MK_COINS(1) >> 1), 10, blk_4);
796  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts(addr_alice_sub_0_2, true, MK_COINS(1) >> 1), 10, blk_4);
797  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts(addr_alice_sub_0_3, true, MK_COINS(1) >> 1), 10, blk_4);
798  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts(addr_alice_sub_0_4, true, MK_COINS(1) >> 1), 10, blk_4);
799 
800  // Sub-address destinations + multi out to force use of additional keys
801  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts({{addr_alice_sub_0_1, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_2, true, MK_COINS(1) >> 1}}), 10, blk_4);
802  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts({{addr_alice_sub_0_1, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_2, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_3, true, MK_COINS(1) >> 1}}), 10, blk_4);
803  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts({{m_miner_account, false, MK_COINS(1) >> 1}, {addr_alice_sub_0_2, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_3, true, MK_COINS(1) >> 1}}), 10, blk_4);
804  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts({{m_miner_account, false, MK_COINS(1) >> 1}, {addr_alice_sub_0_2, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_3, true, MK_COINS(1) >> 1}}), 10, blk_4);
805 
806  // Transfer to other accounts
807  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts(addr_alice_sub_1_0, true, MK_COINS(1) >> 1), 10, blk_4);
808  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts(addr_alice_sub_1_1, true, MK_COINS(1) >> 1), 10, blk_4);
809  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts({{addr_alice_sub_1_0, true, MK_COINS(1) >> 1}, {addr_alice_sub_1_1, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_3, true, MK_COINS(1) >> 1}}), 10, blk_4);
810  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts({{addr_alice_sub_1_1, true, MK_COINS(1) >> 1}, {addr_alice_sub_1_1, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_2, true, MK_COINS(1) >> 1}}), 10, blk_4);
811  MAKE_TX_MIX_DEST_LIST_RCT(events, txs_blk_5, m_miner_account, build_dsts({{addr_alice_sub_1_2, true, MK_COINS(1) >> 1}, {addr_alice_sub_1_1, true, MK_COINS(1) >> 1}, {addr_alice_sub_0_5, true, MK_COINS(1) >> 1}}), 10, blk_4);
812 
813  // Simple RCT transactions
814  MAKE_TX_MIX_LIST_RCT(events, txs_blk_5, m_miner_account, m_alice_account, MK_COINS(7), 10, blk_4);
815  MAKE_TX_MIX_LIST_RCT(events, txs_blk_5, m_miner_account, m_alice_account, MK_COINS(10), 10, blk_4);
816  MAKE_TX_MIX_LIST_RCT(events, txs_blk_5, m_miner_account, m_alice_account, MK_COINS(30), 10, blk_4);
817  MAKE_TX_MIX_LIST_RCT(events, txs_blk_5, m_miner_account, m_alice_account, MK_COINS(40), 10, blk_4);
818  MAKE_NEXT_BLOCK_TX_LIST_HF(events, blk_5, blk_4r, m_miner_account, txs_blk_5, CUR_HF);
819 
820  // Simple transaction check
821  bool resx = rct::verRctSemanticsSimple(txs_blk_5.begin()->rct_signatures);
822  bool resy = rct::verRctNonSemanticsSimple(txs_blk_5.begin()->rct_signatures);
823  CHECK_AND_ASSERT_THROW_MES(resx, "Tsx5[0] semantics failed");
824  CHECK_AND_ASSERT_THROW_MES(resy, "Tsx5[0] non-semantics failed");
825 
826  REWIND_BLOCKS_HF(events, blk_5r, blk_5, m_miner_account, CUR_HF); // rewind to unlock
827 
828  // RCT transactions, wallets have to be used
829  wallet_tools::process_transactions(m_wl_alice.get(), events, blk_5r, m_bt);
830  wallet_tools::process_transactions(m_wl_bob.get(), events, blk_5r, m_bt);
831 
832  // Send Alice -> Bob, manually constructed. Simple TX test, precondition.
834  std::vector<size_t> selected_transfers;
835  std::vector<tx_source_entry> sources;
836  bool res = wallet_tools::fill_tx_sources(m_wl_alice.get(), sources, TREZOR_TEST_MIXIN, boost::none, MK_COINS(2), m_bt, selected_transfers, num_blocks(events) - 1, 0, 1);
837  CHECK_AND_ASSERT_THROW_MES(res, "TX Fill sources failed");
838 
840  events.push_back(tx_1);
841  MAKE_NEXT_BLOCK_TX1_HF(events, blk_6, blk_5r, m_miner_account, tx_1, CUR_HF);
842  MDEBUG("Post 1st tsx: " << (num_blocks(events) - 1) << " at block: " << get_block_hash(blk_6));
843 
844  // Simple transaction check
845  resx = rct::verRctSemanticsSimple(tx_1.rct_signatures);
846  resy = rct::verRctNonSemanticsSimple(tx_1.rct_signatures);
847  CHECK_AND_ASSERT_THROW_MES(resx, "tx_1 semantics failed");
848  CHECK_AND_ASSERT_THROW_MES(resy, "tx_1 non-semantics failed");
849 
850  REWIND_BLOCKS_N_HF(events, blk_6r, blk_6, m_miner_account, 10, CUR_HF);
851  wallet_tools::process_transactions(m_wl_alice.get(), events, blk_6, m_bt);
852  wallet_tools::process_transactions(m_wl_bob.get(), events, blk_6, m_bt);
853  MDEBUG("Available funds on Alice: " << get_available_funds(m_wl_alice.get()));
854  MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get()));
855 
856  m_head = blk_6r;
857  m_events = events;
858  return true;
859 }
860 
861 void gen_trezor_base::load(std::vector<test_event_entry>& events)
862 {
863  init_fields();
864  m_events = events;
865 
866  unsigned acc_idx = 0;
868  unsigned accounts_num = (sizeof(accounts) / sizeof(accounts[0]));
869 
870  for(auto & ev : events)
871  {
872  if (typeid(cryptonote::block) == ev.type())
873  {
874  m_head = boost::get<cryptonote::block>(ev);
875  }
876  else if (typeid(cryptonote::account_base) == ev.type()) // accounts
877  {
878  const auto & acc = boost::get<cryptonote::account_base>(ev);
879  if (acc_idx < accounts_num)
880  {
881  *accounts[acc_idx++] = acc;
882  }
883  }
884  else if (typeid(event_replay_settings) == ev.type()) // hard forks
885  {
886  const auto & rep_settings = boost::get<event_replay_settings>(ev);
887  if (rep_settings.hard_forks)
888  {
889  const auto & hf = rep_settings.hard_forks.get();
890  std::copy(hf.begin(), hf.end(), std::back_inserter(m_hard_forks));
891  }
892  }
893  }
894 
895  // Setup wallets, synchronize blocks
898 
899  setup_trezor();
903 
904  m_wl_alice.reset(new tools::wallet2(m_network_type, 1, true));
905  m_wl_bob.reset(new tools::wallet2(m_network_type, 1, true));
906  m_wl_eve.reset(new tools::wallet2(m_network_type, 1, true));
910 
913  MDEBUG("Available funds on Alice: " << get_available_funds(m_wl_alice.get()));
914  MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get()));
915 }
916 
917 void gen_trezor_base::rewind_blocks(std::vector<test_event_entry>& events, size_t rewind_n, uint8_t hf)
918 {
919  auto & generator = m_generator; // macro shortcut
920  REWIND_BLOCKS_N_HF(events, blk_new, m_head, m_miner_account, rewind_n, hf);
921  m_head = blk_new;
922  m_events = events;
923  MDEBUG("Blocks rewound: " << rewind_n << ", #blocks: " << num_blocks(events) << ", #events: " << events.size());
924 
927 }
928 
929 void gen_trezor_base::fix_hf(std::vector<test_event_entry>& events)
930 {
931  // If current test requires higher hard-fork, move it up
932  const auto current_hf = m_hard_forks.back().first;
933 
934  if (current_hf > m_top_hard_fork)
935  {
936  throw std::runtime_error("Generated chain hardfork is higher than desired maximum");
937  }
938 
939  if (m_rct_config.bp_version == 2 && m_top_hard_fork < 10)
940  {
941  throw std::runtime_error("Desired maximum is too low for BPv2");
942  }
943 
944  if (current_hf < m_top_hard_fork)
945  {
946  auto hardfork_height = num_blocks(events);
947  ADD_HARDFORK(m_hard_forks, m_top_hard_fork, hardfork_height);
948  add_top_hfork(events, m_hard_forks);
949  MDEBUG("Hardfork added at height: " << hardfork_height << ", from " << (int)current_hf << " to " << (int)m_top_hard_fork);
950 
951  if (current_hf < 10)
952  { // buffer blocks, add 10 to apply v10 rules
953  rewind_blocks(events, 10, m_top_hard_fork);
954  }
955  }
956 }
957 
958 void gen_trezor_base::update_trackers(std::vector<test_event_entry>& events)
959 {
961 }
962 
963 void gen_trezor_base::test_setup(std::vector<test_event_entry>& events)
964 {
965  add_shared_events(events);
966 
967  setup_trezor();
969 
972 
973  m_wl_alice.reset(new tools::wallet2(m_network_type, 1, true));
974  m_wl_bob.reset(new tools::wallet2(m_network_type, 1, true));
975  m_wl_eve.reset(new tools::wallet2(m_network_type, 1, true));
982 }
983 
985  std::vector<test_event_entry>& events,
986  test_generator &generator,
987  const std::vector<cryptonote::transaction> &txs)
988 {
989  // If current test requires higher hard-fork, move it up
990  const auto current_hf = m_hard_forks.back().first;
991  const uint8_t tx_hf = m_top_hard_fork;
992  CHECK_AND_ASSERT_THROW_MES(tx_hf <= current_hf, "Too late for HF change: " << (int)tx_hf << " current: " << (int)current_hf);
993  CHECK_AND_ASSERT_THROW_MES(m_rct_config.bp_version < 2 || tx_hf >= 10, "HF too low for BPv2: " << (int)tx_hf);
994 
995  std::list<cryptonote::transaction> tx_list;
996  for(const auto & tx : txs)
997  {
998  events.push_back(tx);
999  tx_list.push_back(tx);
1000  }
1001 
1002  MAKE_NEXT_BLOCK_TX_LIST_HF(events, blk_new, m_head, m_miner_account, tx_list, tx_hf);
1003  MDEBUG("New tsx: " << (num_blocks(events) - 1) << " at block: " << get_block_hash(blk_new));
1004 
1005  m_head = blk_new;
1006 }
1007 
1008 void gen_trezor_base::test_trezor_tx(std::vector<test_event_entry>& events, std::vector<tools::wallet2::pending_tx>& ptxs, std::vector<cryptonote::address_parse_info>& dsts_info, test_generator &generator, std::vector<tools::wallet2*> wallets, bool is_sweep)
1009 {
1010  // Construct pending transaction for signature in the Trezor.
1011  const uint64_t height_pre = num_blocks(events) - 1;
1014 
1016  std::vector<cryptonote::transaction> tx_list;
1017 
1018  for(auto &ptx : ptxs) {
1019  txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(ptx, *m_trezor));
1020  }
1021  txs.transfers = std::make_pair(0, wallet_accessor_test::get_transfers(m_wl_alice.get()));
1022 
1023  auto dev_cold = dynamic_cast<::hw::device_cold*>(m_trezor);
1024  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
1025 
1026  tools::wallet2::signed_tx_set exported_txs;
1027  hw::tx_aux_data aux_data;
1029  setup_shim(&wallet_shim);
1030  aux_data.tx_recipients = dsts_info;
1031  aux_data.bp_version = m_rct_config.bp_version;
1032  dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data);
1033 
1034  MDEBUG("Signed tx data from hw: " << exported_txs.ptx.size() << " transactions");
1035  CHECK_AND_ASSERT_THROW_MES(exported_txs.ptx.size() == ptxs.size(), "Invalid transaction sizes");
1036 
1037  for (size_t i = 0; i < exported_txs.ptx.size(); ++i){
1038  auto &c_ptx = exported_txs.ptx[i];
1039  c_ptx.tx.rct_signatures.mixRing = ptxs[i].tx.rct_signatures.mixRing;
1040  expand_tsx(c_ptx.tx);
1041 
1042  // Simple TX tests, more complex are performed in the core.
1044  bool resx = rct::verRctSemanticsSimple(c_ptx.tx.rct_signatures);
1045  bool resy = rct::verRctNonSemanticsSimple(c_ptx.tx.rct_signatures);
1046  CHECK_AND_ASSERT_THROW_MES(resx, "Trezor tx_1 semantics failed");
1047  CHECK_AND_ASSERT_THROW_MES(resy, "Trezor tx_1 Nonsemantics failed");
1048 
1049  tx_list.push_back(c_ptx.tx);
1050  MDEBUG("Transaction: " << dump_data(c_ptx.tx));
1051  }
1052 
1053  add_transactions_to_events(events, generator, tx_list);
1054 
1055  // TX receive test
1056  uint64_t sum_in = 0;
1057  uint64_t sum_out = 0;
1058 
1059  for(size_t txid = 0; txid < exported_txs.ptx.size(); ++txid) {
1060  auto &c_ptx = exported_txs.ptx[txid];
1061  auto &c_tx = c_ptx.tx;
1062  const crypto::hash txhash = cryptonote::get_transaction_hash(c_tx);
1063  const size_t num_outs = c_tx.vout.size();
1064  size_t num_received = 0;
1065  uint64_t cur_sum_in = 0;
1066  uint64_t cur_sum_out = 0;
1067  uint64_t cur_sum_out_recv = 0;
1068  std::unordered_set<size_t> recv_out_idx;
1069  std::string exp_payment_id = get_payment_id(c_ptx.construction_data.extra);
1070  std::string enc_payment_id = get_payment_id(c_tx.extra);
1071  size_t num_payment_id_checks_done = 0;
1072 
1073  CHECK_AND_ASSERT_THROW_MES(exp_payment_id.empty() || exp_payment_id.size() == 8 || exp_payment_id.size() == 32, "Required payment ID invalid");
1074  CHECK_AND_ASSERT_THROW_MES((exp_payment_id.size() == 32) == (enc_payment_id.size() == 32), "Required and built payment ID size mismatch");
1075  CHECK_AND_ASSERT_THROW_MES(exp_payment_id.size() <= enc_payment_id.size(), "Required and built payment ID size mismatch");
1076 
1077  for(auto &src : c_ptx.construction_data.sources){
1078  cur_sum_in += src.amount;
1079  }
1080 
1081  for(auto &dst : c_ptx.construction_data.splitted_dsts){
1082  cur_sum_out += dst.amount;
1083  }
1084 
1085  CHECK_AND_ASSERT_THROW_MES(c_tx.rct_signatures.txnFee + cur_sum_out == cur_sum_in, "Tx Input Output amount mismatch");
1086 
1087  for (size_t widx = 0; widx < wallets.size(); ++widx) {
1088  const bool sender = widx == 0;
1089  tools::wallet2 *wl = wallets[widx];
1090 
1091  wallet_tools::process_transactions(wl, events, m_head, m_bt, boost::make_optional(head_hash));
1092 
1095  wl->get_transfers(m_trans);
1096 
1097  std::copy_if(m_trans.begin(), m_trans.end(), std::back_inserter(m_trans_txid), [&txhash](const tools::wallet2::transfer_details& item) {
1098  return item.m_txid == txhash;
1099  });
1100 
1101  // Testing if the transaction output has been received
1102  num_received += m_trans_txid.size();
1103  for (auto & ctran : m_trans_txid){
1104  cur_sum_out_recv += ctran.amount();
1105  recv_out_idx.insert(ctran.m_internal_output_index);
1106  CHECK_AND_ASSERT_THROW_MES(!ctran.m_spent, "Txout is spent");
1107  CHECK_AND_ASSERT_THROW_MES(!sender || ctran.m_key_image_known, "Key Image unknown for recipient"); // sender is Trezor, does not need to have KI
1108  }
1109 
1110  // Sender output payment (contains change and stuff)
1111  if (sender) {
1112  std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> confirmed_transfers; // txid -> tdetail
1113  std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> confirmed_transfers_txid; // txid -> tdetail
1114  wl->get_payments_out(confirmed_transfers, height_pre);
1115 
1116  std::copy_if(confirmed_transfers.begin(), confirmed_transfers.end(), std::back_inserter(confirmed_transfers_txid), [&txhash](const std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>& item) {
1117  return item.first == txhash;
1118  });
1119 
1120  CHECK_AND_ASSERT_THROW_MES(confirmed_transfers_txid.size() == 1, "Sender does not have outgoing transfer for the transaction");
1121  }
1122 
1123  // Received payment from the block
1124  std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments; // payment id -> [payment details] multimap
1125  std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments_txid; // payment id -> [payment details] multimap
1126  wl->get_payments(payments, height_pre);
1127 
1128  std::copy_if(payments.begin(), payments.end(), std::back_inserter(payments_txid), [&txhash](const std::pair<crypto::hash, tools::wallet2::payment_details>& item) {
1129  return item.second.m_tx_hash == txhash;
1130  });
1131 
1132  for(auto &paydet : payments_txid){
1133  CHECK_AND_ASSERT_THROW_MES(exp_payment_id.empty() || (memcmp(exp_payment_id.data(), paydet.first.data, exp_payment_id.size()) == 0), "Payment ID mismatch");
1134  num_payment_id_checks_done += 1;
1135  }
1136  }
1137 
1138  CHECK_AND_ASSERT_THROW_MES(c_tx.rct_signatures.txnFee + cur_sum_out_recv == cur_sum_in, "Tx Input Output amount mismatch");
1139  CHECK_AND_ASSERT_THROW_MES(exp_payment_id.empty() || num_payment_id_checks_done > 0, "No Payment ID checks");
1140 
1141  if(!is_sweep){
1142  CHECK_AND_ASSERT_THROW_MES(num_received == num_outs, "Number of received outputs do not match number of outgoing");
1143  CHECK_AND_ASSERT_THROW_MES(recv_out_idx.size() == num_outs, "Num of outs received do not match");
1144  } else {
1145  CHECK_AND_ASSERT_THROW_MES(num_received + 1 >= num_outs, "Number of received outputs do not match number of outgoing");
1146  CHECK_AND_ASSERT_THROW_MES(recv_out_idx.size() + 1 >= num_outs, "Num of outs received do not match"); // can have dummy out
1147  }
1148 
1149  sum_in += cur_sum_in;
1150  sum_out += cur_sum_out + c_tx.rct_signatures.txnFee;
1151  }
1152 
1153  CHECK_AND_ASSERT_THROW_MES(sum_in == sum_out, "Tx amount mismatch");
1154 
1155  // Test get_tx_key feature for stored private tx keys
1156  test_get_tx(events, wallets, exported_txs.ptx, aux_data.tx_device_aux);
1157 }
1158 
1160 {
1161  ::crypto::public_key tx_pub_c;
1162  ::crypto::secret_key_to_public_key(tx_priv, tx_pub_c);
1163  if (tx_pub == tx_pub_c)
1164  return true;
1165 
1166  for(const auto & elem : subs)
1167  {
1168  tx_pub_c = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(elem.first), rct::sk2rct(tx_priv)));
1169  if (tx_pub == tx_pub_c)
1170  return true;
1171  }
1172  return false;
1173 }
1174 
1176  std::vector<test_event_entry>& events,
1177  std::vector<tools::wallet2*> wallets,
1178  const std::vector<tools::wallet2::pending_tx> &ptxs,
1179  const std::vector<std::string> &aux_tx_info)
1180 {
1181  if (!m_test_get_tx_key)
1182  {
1183  return;
1184  }
1185 
1186  auto dev_cold = dynamic_cast<::hw::device_cold*>(m_trezor);
1187  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
1188 
1189  if (!dev_cold->is_get_tx_key_supported())
1190  {
1191  MERROR("Get TX key is not supported by the connected Trezor");
1192  return;
1193  }
1194 
1195  subaddresses_t all_subs;
1196  for(tools::wallet2 * wlt : wallets)
1197  {
1198  wlt->expand_subaddresses({10, 20});
1199 
1201  all_subs.insert(cur_sub.begin(), cur_sub.end());
1202  }
1203 
1204  for(size_t txid = 0; txid < ptxs.size(); ++txid)
1205  {
1206  const auto &c_ptx = ptxs[txid];
1207  const auto &c_tx = c_ptx.tx;
1209 
1210  auto tx_pub = cryptonote::get_tx_pub_key_from_extra(c_tx.extra);
1211  auto additional_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(c_tx.extra);
1212 
1213  hw::device_cold:: tx_key_data_t tx_key_data;
1214  std::vector<::crypto::secret_key> tx_keys;
1215 
1216  dev_cold->load_tx_key_data(tx_key_data, aux_tx_info[txid]);
1217  CHECK_AND_ASSERT_THROW_MES(std::string(tx_prefix_hash.data, 32) == tx_key_data.tx_prefix_hash, "TX prefix mismatch");
1218 
1219  dev_cold->get_tx_key(tx_keys, tx_key_data, m_alice_account.get_keys().m_view_secret_key);
1220  CHECK_AND_ASSERT_THROW_MES(!tx_keys.empty(), "Empty TX keys");
1221  CHECK_AND_ASSERT_THROW_MES(verify_tx_key(tx_keys[0], tx_pub, all_subs), "Tx pub mismatch");
1222  CHECK_AND_ASSERT_THROW_MES(additional_pub_keys.size() == tx_keys.size() - 1, "Invalid additional keys count");
1223 
1224  for(size_t i = 0; i < additional_pub_keys.size(); ++i)
1225  {
1226  CHECK_AND_ASSERT_THROW_MES(verify_tx_key(tx_keys[i + 1], additional_pub_keys[i], all_subs), "Tx pub mismatch");
1227  }
1228  }
1229 }
1230 
1231 void gen_trezor_base::mine_and_test(std::vector<test_event_entry>& events)
1232 {
1233  cryptonote::core * core = daemon()->core();
1234  const uint64_t height_before_mining = daemon()->get_height();
1235 
1236  const auto miner_address = cryptonote::get_account_address_as_str(FAKECHAIN, false, get_address(m_miner_account));
1237  daemon()->mine_blocks(1, miner_address);
1238 
1239  const uint64_t cur_height = daemon()->get_height();
1240  CHECK_AND_ASSERT_THROW_MES(height_before_mining < cur_height, "Mining fail");
1241 
1242  const crypto::hash top_hash = core->get_blockchain_storage().get_block_id_by_height(height_before_mining);
1243  cryptonote::block top_block{};
1244  CHECK_AND_ASSERT_THROW_MES(core->get_blockchain_storage().get_block_by_hash(top_hash, top_block), "Block fetch fail");
1245  CHECK_AND_ASSERT_THROW_MES(!top_block.tx_hashes.empty(), "Mined block is empty");
1246 
1247  std::vector<cryptonote::transaction> txs_found;
1248  std::vector<crypto::hash> txs_missed;
1249  bool r = core->get_blockchain_storage().get_transactions(top_block.tx_hashes, txs_found, txs_missed);
1250  CHECK_AND_ASSERT_THROW_MES(r, "Transaction lookup fail");
1251  CHECK_AND_ASSERT_THROW_MES(!txs_found.empty(), "Transaction lookup fail");
1252 
1253  // Transaction is not expanded, but mining verified it.
1254  events.push_back(txs_found[0]);
1255  events.push_back(top_block);
1256 }
1257 
1259 {
1260  m_top_hard_fork = hf;
1261  if (hf < 9){
1262  throw std::runtime_error("Minimal supported Hardfork is 9");
1263  } else if (hf == 9){
1265  } else {
1267  }
1268 }
1269 
1270 #define TREZOR_TEST_PREFIX() \
1271  test_generator generator(m_generator); \
1272  test_setup(events); \
1273  tsx_builder t_builder_o(this); \
1274  tsx_builder * t_builder = &t_builder_o
1275 
1276 #define TREZOR_TEST_SUFFIX() \
1277  auto _dsts = t_builder->build(); \
1278  auto _dsts_info = t_builder->dest_info(); \
1279  test_trezor_tx(events, _dsts, _dsts_info, generator, vct_wallets(m_wl_alice.get(), m_wl_bob.get(), m_wl_eve.get())); \
1280  return true
1281 
1282 #define TREZOR_SKIP_IF_VERSION_LEQ(x) if (m_trezor->get_version() <= x) { MDEBUG("Test skipped"); return true; }
1283 #define TREZOR_TEST_PAYMENT_ID "\xde\xad\xc0\xde\xde\xad\xc0\xde"
1284 #define TREZOR_TEST_PAYMENT_ID_LONG "\xde\xad\xc0\xde\xde\xad\xc0\xde\xde\xad\xc0\xde\xde\xad\xc0\xde\xde\xad\xc0\xde\xde\xad\xc0\xde\xde\xad\xc0\xde\xde\xad\xc0\xde"
1285 
1286 tsx_builder * tsx_builder::sources(std::vector<cryptonote::tx_source_entry> & sources, std::vector<size_t> & selected_transfers)
1287 {
1288  m_sources = sources;
1289  m_selected_transfers = selected_transfers;
1290  return this;
1291 }
1292 
1293 tsx_builder * tsx_builder::compute_sources(boost::optional<size_t> num_utxo, boost::optional<uint64_t> min_amount, ssize_t offset, int step, boost::optional<fnc_accept_tx_source_t> fnc_accept)
1294 {
1295  CHECK_AND_ASSERT_THROW_MES(m_tester, "m_tester wallet empty");
1296  CHECK_AND_ASSERT_THROW_MES(m_from, "m_from wallet empty");
1297 
1298  // typedef std::function<bool(const tx_source_info_crate_t &info, bool &abort)> fnc_accept_tx_source_t;
1299  boost::optional<fnc_accept_tx_source_t> fnc_accept_to_use = boost::none;
1300 
1301  auto c_account = m_account;
1302  fnc_accept_tx_source_t fnc_acc = [c_account, &fnc_accept] (const tx_source_info_crate_t &info, bool &abort) -> bool {
1303  if (info.td->m_subaddr_index.major != c_account){
1304  return false;
1305  }
1306  if (fnc_accept){
1307  return (fnc_accept.get())(info, abort);
1308  }
1309  return true;
1310  };
1311 
1312  fnc_accept_to_use = fnc_acc;
1313  bool res = wallet_tools::fill_tx_sources(m_from, m_sources, m_mixin, num_utxo, min_amount, m_tester->m_bt, m_selected_transfers, m_cur_height, offset, step, fnc_accept_to_use);
1314  CHECK_AND_ASSERT_THROW_MES(res, "Tx source fill error");
1315  return this;
1316 }
1317 
1318 tsx_builder * tsx_builder::compute_sources_to_sub(boost::optional<size_t> num_utxo, boost::optional<uint64_t> min_amount, ssize_t offset, int step, boost::optional<fnc_accept_tx_source_t> fnc_accept)
1319 {
1320  fnc_accept_tx_source_t fnc = [&fnc_accept] (const tx_source_info_crate_t &info, bool &abort) -> bool {
1321  if (info.td->m_subaddr_index.minor == 0){
1322  return false;
1323  }
1324  if (fnc_accept){
1325  return (fnc_accept.get())(info, abort);
1326  }
1327  return true;
1328  };
1329 
1330  return compute_sources(num_utxo, min_amount, offset, step, fnc);
1331 }
1332 
1333 tsx_builder * tsx_builder::compute_sources_to_sub_acc(boost::optional<size_t> num_utxo, boost::optional<uint64_t> min_amount, ssize_t offset, int step, boost::optional<fnc_accept_tx_source_t> fnc_accept)
1334 {
1335  fnc_accept_tx_source_t fnc = [&fnc_accept] (const tx_source_info_crate_t &info, bool &abort) -> bool {
1336  if (info.td->m_subaddr_index.minor == 0 || info.src->real_out_additional_tx_keys.size() == 0){
1337  return false;
1338  }
1339  if (fnc_accept){
1340  return (fnc_accept.get())(info, abort);
1341  }
1342  return true;
1343  };
1344 
1345  return compute_sources(num_utxo, min_amount, offset, step, fnc);
1346 }
1347 
1348 tsx_builder * tsx_builder::destinations(std::vector<cryptonote::tx_destination_entry> &dsts)
1349 {
1350  m_destinations_orig = dsts;
1351  return this;
1352 }
1353 
1355 {
1356  m_destinations_orig.push_back(dst);
1357  return this;
1358 }
1359 
1360 tsx_builder * tsx_builder::add_destination(const var_addr_t addr, bool is_subaddr, uint64_t amount)
1361 {
1362  m_destinations_orig.push_back(build_dst(addr, is_subaddr, amount));
1363  return this;
1364 }
1365 
1366 tsx_builder * tsx_builder::add_destination(const tools::wallet2 * wallet, bool is_subaddr, uint64_t amount)
1367 {
1368  m_destinations_orig.push_back(build_dst(get_address(wallet), is_subaddr, amount));
1369  return this;
1370 }
1371 
1373 {
1374  m_integrated.insert(idx);
1375  return this;
1376 }
1377 
1379 {
1380  m_account = 0;
1381  m_selected_transfers.clear();
1382  m_sources.clear();
1383  m_destinations.clear();
1384  m_destinations_orig.clear();
1385  m_dsts_info.clear();
1386  m_integrated.clear();
1387  m_payment_id.clear();
1388  return this;
1389 }
1390 
1392 {
1393  CHECK_AND_ASSERT_THROW_MES(m_tester, "m_tester wallet empty");
1394  CHECK_AND_ASSERT_THROW_MES(m_from, "m_from wallet empty");
1395 
1396  // Amount sanity check input >= fee + outputs
1397  const uint64_t out_amount = sum_amount(m_destinations_orig);
1398  const uint64_t in_amount = sum_amount(m_sources);
1399  CHECK_AND_ASSERT_THROW_MES(in_amount >= out_amount + m_fee, "Not enough input credits for outputs and fees");
1400 
1401  // Create new pending transaction, init with sources and destinations
1402  m_ptxs.emplace_back();
1403  auto & ptx = m_ptxs.back();
1404 
1405  std::vector<uint8_t> extra = build_payment_id_extra(m_payment_id);
1407  construct_pending_tx(ptx, extra);
1408 
1410 
1411  // Build destinations parse info
1412  for(size_t i = 0; i < m_destinations_orig.size(); ++i){
1413  auto & cdest = m_destinations_orig[i];
1414  cryptonote::address_parse_info info = init_addr_parse_info(cdest.addr, cdest.is_subaddress);
1415  if (m_integrated.find(i) != m_integrated.end()){
1416  CHECK_AND_ASSERT_THROW_MES(m_payment_id.size() == 8, "Integrated set but payment_id.size() != 8");
1417  info.has_payment_id = true;
1418  info.payment_id = to_short_payment_id(m_payment_id);
1419  }
1420 
1421  m_dsts_info.push_back(info);
1422  }
1423 
1424  return this;
1425 }
1426 
1427 tsx_builder * tsx_builder::construct_pending_tx(tools::wallet2::pending_tx &ptx, boost::optional<std::vector<uint8_t>> extra)
1428 {
1429  CHECK_AND_ASSERT_THROW_MES(m_from, "Wallet not provided");
1430 
1433  crypto::secret_key tx_key;
1434  std::vector<crypto::secret_key> additional_tx_keys;
1435  std::vector<tx_destination_entry> destinations_copy = m_destinations;
1436 
1437  auto change_addr = m_from->get_account().get_keys().m_account_address;
1438  bool r = construct_tx_and_get_tx_key(m_from->get_account().get_keys(), subaddresses, m_sources, destinations_copy,
1439  change_addr, extra ? extra.get() : std::vector<uint8_t>(), tx, 0, tx_key,
1440  additional_tx_keys, true, m_rct_config, nullptr);
1441 
1442  CHECK_AND_ASSERT_THROW_MES(r, "Transaction construction failed");
1443 
1444  ptx.key_images = "";
1445  ptx.fee = TESTS_DEFAULT_FEE;
1446  ptx.dust = 0;
1447  ptx.dust_added_to_fee = false;
1448  ptx.tx = tx;
1449  ptx.change_dts = m_destinations.back();
1451  ptx.tx_key = tx_key;
1452  ptx.additional_tx_keys = additional_tx_keys;
1453  ptx.dests = m_destinations;
1454  ptx.multisig_sigs.clear();
1459  ptx.construction_data.extra = tx.extra;
1461  ptx.construction_data.use_rct = true;
1464 
1466  ptx.construction_data.subaddr_indices.clear();
1467  for(uint32_t i = 0; i < 20; ++i)
1468  ptx.construction_data.subaddr_indices.insert(i);
1469 
1470  return this;
1471 }
1472 
1473 std::vector<tools::wallet2::pending_tx> tsx_builder::build()
1474 {
1475  return m_ptxs;
1476 }
1477 
1478 device_trezor_test::device_trezor_test(): m_tx_sign_ctr(0), m_compute_key_image_ctr(0) {}
1479 
1481  m_tx_sign_ctr = 0;
1483 }
1484 
1486  this->clear_test_counters();
1487  this->set_callback(nullptr);
1488  this->set_debug(true); // debugging commands on Trezor (auto-confirm transactions)
1489 
1490  CHECK_AND_ASSERT_THROW_MES(this->set_name(trezor_path), "Could not set device name " << trezor_path);
1491  this->set_network_type(network_type);
1492  this->set_derivation_path(""); // empty derivation path
1493 
1494  CHECK_AND_ASSERT_THROW_MES(this->init(), "Could not initialize the device " << trezor_path);
1495  CHECK_AND_ASSERT_THROW_MES(this->connect(), "Could not connect to the device " << trezor_path);
1496  this->wipe_device();
1497  this->load_device(seed);
1498  this->release();
1499  this->disconnect();
1500 }
1501 
1502 bool device_trezor_test::compute_key_image(const ::cryptonote::account_keys &ack, const ::crypto::public_key &out_key,
1503  const ::crypto::key_derivation &recv_derivation, size_t real_output_index,
1504  const ::cryptonote::subaddress_index &received_index,
1505  ::cryptonote::keypair &in_ephemeral, ::crypto::key_image &ki) {
1506 
1507  bool res = device_trezor::compute_key_image(ack, out_key, recv_derivation, real_output_index, received_index,
1508  in_ephemeral, ki);
1510  return res;
1511 }
1512 
1513 void
1515  hw::tx_aux_data &aux_data, std::shared_ptr<hw::trezor::protocol::tx::Signer> &signer) {
1516  m_tx_sign_ctr += 1;
1517  device_trezor::tx_sign(wallet, unsigned_tx, idx, aux_data, signer);
1518 }
1519 
1520 bool gen_trezor_ki_sync::generate(std::vector<test_event_entry>& events)
1521 {
1522  test_generator generator(m_generator);
1523  test_setup(events);
1524 
1525  auto dev_cold = dynamic_cast<::hw::device_cold*>(m_trezor);
1526  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
1527 
1528  std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
1531  setup_shim(&wallet_shim);
1532  m_wl_alice->get_transfers(transfers);
1533 
1534  dev_cold->ki_sync(&wallet_shim, transfers, ski);
1535  CHECK_AND_ASSERT_THROW_MES(ski.size() == transfers.size(), "Size mismatch");
1536  for(size_t i = 0; i < transfers.size(); ++i)
1537  {
1538  auto & td = transfers[i];
1539  auto & kip = ski[i];
1540  CHECK_AND_ASSERT_THROW_MES(!td.m_key_image_known || td.m_key_image == kip.first, "Key Image invalid: " << i);
1541  }
1542 
1543  uint64_t spent = 0, unspent = 0;
1544  m_wl_alice->import_key_images(ski, 0, spent, unspent, false);
1545 
1546  auto dev_trezor_test = dynamic_cast<device_trezor_test*>(m_trezor);
1547  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement test interface");
1549  CHECK_AND_ASSERT_THROW_MES(dev_trezor_test->m_compute_key_image_ctr == 0, "Live refresh should not happen: " << dev_trezor_test->m_compute_key_image_ctr);
1550  else
1551  CHECK_AND_ASSERT_THROW_MES(dev_trezor_test->m_compute_key_image_ctr == ski.size(), "Live refresh counts invalid");
1552 
1553  return true;
1554 }
1555 
1556 bool gen_trezor_ki_sync_with_refresh::generate(std::vector<test_event_entry>& events)
1557 {
1558  m_live_refresh_enabled = true;
1559  return gen_trezor_ki_sync::generate(events);
1560 }
1561 
1562 bool gen_trezor_ki_sync_without_refresh::generate(std::vector<test_event_entry>& events)
1563 {
1564  m_live_refresh_enabled = false;
1565  return gen_trezor_ki_sync::generate(events);
1566 }
1567 
1568 bool gen_trezor_live_refresh::generate(std::vector<test_event_entry>& events)
1569 {
1570  test_generator generator(m_generator);
1571  test_setup(events);
1572 
1573  auto dev_cold = dynamic_cast<::hw::device_cold*>(m_trezor);
1574  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
1575 
1576  if (!dev_cold->is_live_refresh_supported()){
1577  MDEBUG("Trezor does not support live refresh");
1578  return true;
1579  }
1580 
1581  hw::device & sw_device = hw::get_device("default");
1582 
1583  dev_cold->live_refresh_start();
1584  for(unsigned i=0; i<50; ++i)
1585  {
1586  cryptonote::subaddress_index subaddr = {0, i};
1587 
1591  ::crypto::public_key pub_ver;
1593 
1594  ::crypto::random32_unbiased((unsigned char*)r.data);
1596  memcpy(D.data, rct::scalarmultKey(rct::pk2rct(R), rct::sk2rct(m_alice_account.get_keys().m_view_secret_key)).bytes, 32);
1597 
1598  ::crypto::secret_key scalar_step1;
1599  ::crypto::secret_key scalar_step2;
1601  if (i == 0)
1602  {
1603  scalar_step2 = scalar_step1;
1604  }
1605  else
1606  {
1608  sw_device.sc_secret_add(scalar_step2, scalar_step1, subaddr_sk);
1609  }
1610 
1611  ::crypto::secret_key_to_public_key(scalar_step2, pub_ver);
1612  ::crypto::generate_key_image(pub_ver, scalar_step2, ki);
1613 
1614  cryptonote::keypair in_ephemeral;
1615  ::crypto::key_image ki2;
1616 
1617  dev_cold->live_refresh(
1619  pub_ver,
1620  D,
1621  i,
1622  subaddr,
1623  in_ephemeral,
1624  ki2
1625  );
1626 
1627  CHECK_AND_ASSERT_THROW_MES(ki == ki2, "Key image inconsistent");
1628  }
1629 
1630  dev_cold->live_refresh_finish();
1631  return true;
1632 }
1633 
1634 bool gen_trezor_1utxo::generate(std::vector<test_event_entry>& events)
1635 {
1637  t_builder->cur_height(num_blocks(events) - 1)
1638  ->mixin(TREZOR_TEST_MIXIN)
1639  ->fee(TREZOR_TEST_FEE)
1640  ->from(m_wl_alice.get(), 0)
1641  ->compute_sources(boost::none, MK_COINS(1), -1, -1)
1642  ->add_destination(m_eve_account, false, 1000)
1643  ->rct_config(m_rct_config)
1644  ->build_tx();
1645 
1647 }
1648 
1649 bool gen_trezor_1utxo_paymentid_short::generate(std::vector<test_event_entry>& events)
1650 {
1653  t_builder->cur_height(num_blocks(events) - 1)
1654  ->mixin(TREZOR_TEST_MIXIN)
1655  ->fee(TREZOR_TEST_FEE)
1656  ->from(m_wl_alice.get(), 0)
1657  ->compute_sources(boost::none, MK_COINS(1), -1, -1)
1658  ->add_destination(m_eve_account, false, 1000)
1659  ->payment_id(TREZOR_TEST_PAYMENT_ID)
1660  ->rct_config(m_rct_config)
1661  ->build_tx();
1662 
1664 }
1665 
1666 bool gen_trezor_1utxo_paymentid_short_integrated::generate(std::vector<test_event_entry>& events)
1667 {
1670  t_builder->cur_height(num_blocks(events) - 1)
1671  ->mixin(TREZOR_TEST_MIXIN)
1672  ->fee(TREZOR_TEST_FEE)
1673  ->from(m_wl_alice.get(), 0)
1674  ->compute_sources(boost::none, MK_COINS(1), -1, -1)
1675  ->add_destination(m_eve_account, false, 1000)
1676  ->payment_id(TREZOR_TEST_PAYMENT_ID)
1677  ->set_integrated(0)
1678  ->rct_config(m_rct_config)
1679  ->build_tx();
1680 
1682 }
1683 
1684 bool gen_trezor_1utxo_paymentid_long::generate(std::vector<test_event_entry>& events)
1685 {
1687  t_builder->cur_height(num_blocks(events) - 1)
1688  ->mixin(TREZOR_TEST_MIXIN)
1689  ->fee(TREZOR_TEST_FEE)
1690  ->from(m_wl_alice.get(), 0)
1691  ->compute_sources(boost::none, MK_COINS(1), -1, -1)
1692  ->add_destination(m_eve_account, false, 1000)
1693  ->payment_id(TREZOR_TEST_PAYMENT_ID_LONG)
1694  ->rct_config(m_rct_config)
1695  ->build_tx();
1696 
1698 }
1699 
1700 bool gen_trezor_4utxo::generate(std::vector<test_event_entry>& events)
1701 {
1703  t_builder->cur_height(num_blocks(events) - 1)
1704  ->mixin(TREZOR_TEST_MIXIN)
1705  ->fee(TREZOR_TEST_FEE)
1706  ->from(m_wl_alice.get(), 0)
1707  ->compute_sources(4, MK_COINS(1), -1, -1)
1708  ->add_destination(m_eve_account, false, 1000)
1709  ->rct_config(m_rct_config)
1710  ->build_tx();
1711 
1713 }
1714 
1715 bool gen_trezor_4utxo_acc1::generate(std::vector<test_event_entry>& events)
1716 {
1718  t_builder->cur_height(num_blocks(events) - 1)
1719  ->mixin(TREZOR_TEST_MIXIN)
1720  ->fee(TREZOR_TEST_FEE)
1721  ->from(m_wl_alice.get(), 1)
1722  ->compute_sources(4, MK_COINS(1), -1, -1)
1723  ->add_destination(m_wl_eve->get_subaddress({0, 1}), true, 1000)
1725  ->build_tx();
1726 
1728 }
1729 
1730 bool gen_trezor_4utxo_to_sub::generate(std::vector<test_event_entry>& events)
1731 {
1733  t_builder->cur_height(num_blocks(events) - 1)
1734  ->mixin(TREZOR_TEST_MIXIN)
1735  ->fee(TREZOR_TEST_FEE)
1736  ->from(m_wl_alice.get(), 0)
1737  ->compute_sources(4, MK_COINS(1), -1, -1)
1738  ->add_destination(m_wl_eve->get_subaddress({0, 1}), true, 1000)
1740  ->build_tx();
1741 
1743 }
1744 
1745 bool gen_trezor_4utxo_to_2sub::generate(std::vector<test_event_entry>& events)
1746 {
1748  t_builder->cur_height(num_blocks(events) - 1)
1749  ->mixin(TREZOR_TEST_MIXIN)
1750  ->fee(TREZOR_TEST_FEE)
1751  ->from(m_wl_alice.get(), 0)
1752  ->compute_sources(4, MK_COINS(1), -1, -1)
1753  ->add_destination(m_wl_eve->get_subaddress({0, 1}), true, 1000)
1754  ->add_destination(m_wl_eve->get_subaddress({1, 3}), true, 1000)
1756  ->build_tx();
1757 
1759 }
1760 
1761 bool gen_trezor_4utxo_to_1norm_2sub::generate(std::vector<test_event_entry>& events)
1762 {
1764  t_builder->cur_height(num_blocks(events) - 1)
1765  ->mixin(TREZOR_TEST_MIXIN)
1766  ->fee(TREZOR_TEST_FEE)
1767  ->from(m_wl_alice.get(), 0)
1768  ->compute_sources(4, MK_COINS(1), -1, -1)
1769  ->add_destination(m_wl_eve->get_subaddress({1, 1}), true, 1000)
1770  ->add_destination(m_wl_eve->get_subaddress({2, 1}), true, 1000)
1771  ->add_destination(m_wl_eve.get(), false, 1000)
1773  ->build_tx();
1774 
1776 }
1777 
1778 bool gen_trezor_2utxo_sub_acc_to_1norm_2sub::generate(std::vector<test_event_entry>& events)
1779 {
1781  t_builder->cur_height(num_blocks(events) - 1)
1782  ->mixin(TREZOR_TEST_MIXIN)
1783  ->fee(TREZOR_TEST_FEE)
1784  ->from(m_wl_alice.get(), 0)
1785  ->compute_sources_to_sub_acc(2, MK_COINS(1) >> 2, -1, -1)
1786  ->add_destination(m_wl_eve->get_subaddress({1, 1}), true, 1000)
1787  ->add_destination(m_wl_eve->get_subaddress({2, 1}), true, 1000)
1788  ->add_destination(m_wl_eve.get(), false, 1000)
1790  ->build_tx();
1791 
1793 }
1794 
1795 bool gen_trezor_4utxo_to_7outs::generate(std::vector<test_event_entry>& events)
1796 {
1798  t_builder->cur_height(num_blocks(events) - 1)
1799  ->mixin(TREZOR_TEST_MIXIN)
1800  ->fee(TREZOR_TEST_FEE)
1801  ->from(m_wl_alice.get(), 0)
1802  ->compute_sources(4, MK_COINS(1), -1, -1)
1803  ->add_destination(m_wl_eve->get_subaddress({1, 1}), true, 1000)
1804  ->add_destination(m_wl_eve->get_subaddress({2, 1}), true, 1000)
1805  ->add_destination(m_wl_eve->get_subaddress({0, 1}), true, 1000)
1806  ->add_destination(m_wl_eve->get_subaddress({0, 2}), true, 1000)
1807  ->add_destination(m_wl_eve->get_subaddress({0, 3}), true, 1000)
1808  ->add_destination(m_wl_eve->get_subaddress({0, 4}), true, 1000)
1809  ->add_destination(m_wl_eve.get(), false, 1000)
1811  ->build_tx();
1812 
1814 }
1815 
1816 bool gen_trezor_many_utxo::generate(std::vector<test_event_entry>& events)
1817 {
1819  t_builder->cur_height(num_blocks(events) - 1)
1820  ->mixin(TREZOR_TEST_MIXIN)
1821  ->fee(TREZOR_TEST_FEE)
1822  ->from(m_wl_alice.get(), 0)
1823  ->compute_sources(110, MK_COINS(1), -1, -1)
1824  ->add_destination(m_eve_account, false, 1000)
1825  ->rct_config(m_rct_config)
1826  ->build_tx();
1827 
1829 }
1830 
1832 {
1833  m_wallet_dir = boost::filesystem::unique_path();
1834  boost::filesystem::create_directories(m_wallet_dir);
1835 }
1836 
1838 {
1839  try
1840  {
1841  if (!m_wallet_dir.empty() && boost::filesystem::exists(m_wallet_dir))
1842  {
1843  boost::filesystem::remove_all(m_wallet_dir);
1844  }
1845  }
1846  catch(...)
1847  {
1848  MERROR("Could not remove wallet directory");
1849  }
1850 }
1851 
1852 bool wallet_api_tests::generate(std::vector<test_event_entry>& events)
1853 {
1854  init();
1855  test_setup(events);
1856  const std::string wallet_path = (m_wallet_dir / "wallet").string();
1857  const auto api_net_type = m_network_type == TESTNET ? Electroneum::TESTNET : Electroneum::MAINNET;
1858 
1860  std::unique_ptr<Electroneum::Wallet> w{wmgr->createWalletFromDevice(wallet_path, "", api_net_type, m_trezor_path, 1)};
1861  CHECK_AND_ASSERT_THROW_MES(w->init(daemon()->rpc_addr(), 0), "Wallet init fail");
1862  CHECK_AND_ASSERT_THROW_MES(w->refresh(), "Refresh fail");
1863  uint64_t balance = w->balance(0);
1864  MDEBUG("Balance: " << balance);
1866 
1867  auto addr = get_address(m_eve_account);
1868  auto recepient_address = cryptonote::get_account_address_as_str(m_network_type, false, addr);
1869  Electroneum::PendingTransaction * transaction = w->createTransaction(recepient_address,
1870  "",
1871  MK_COINS(10),
1874  0,
1875  std::set<uint32_t>{});
1877  w->refresh();
1878 
1879  CHECK_AND_ASSERT_THROW_MES(w->balance(0) == balance, "Err");
1880  CHECK_AND_ASSERT_THROW_MES(transaction->amount() == MK_COINS(10), "Err");
1881  CHECK_AND_ASSERT_THROW_MES(transaction->commit(), "Err");
1882  CHECK_AND_ASSERT_THROW_MES(w->balance(0) != balance, "Err");
1883  CHECK_AND_ASSERT_THROW_MES(wmgr->closeWallet(w.get()), "Err");
1884  (void)w.release();
1885 
1886  mine_and_test(events);
1887  return true;
1888 }
1889 
const char * res
Definition: hmac_keccak.cpp:41
bool generate(std::vector< test_event_entry > &events) override
Definition: daemon.h:76
const char *const ELECTRONEUM_RELEASE_NAME
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
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) override
#define MERROR(x)
Definition: misc_log_ex.h:73
const config_t & get_config(network_type nettype)
bool generate(std::vector< test_event_entry > &events) override
cryptonote::transaction tx
Definition: wallet2.h:466
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
cryptonote::network_type m_network_type
Definition: trezor_tests.h:117
virtual bool verify_tx_key(const ::crypto::secret_key &tx_priv, const ::crypto::public_key &tx_pub, const subaddresses_t &subs)
boost::function< crypto::public_key(const tools::wallet2::transfer_details &td)> get_tx_pub_key_from_received_outs
Definition: device_cold.hpp:41
bool deinit()
performs safe shutdown steps for core and core components
virtual void test_setup(std::vector< test_event_entry > &events)
rct::RCTConfig m_rct_config
Definition: trezor_tests.h:128
bool extract_hard_forks(const std::vector< test_event_entry > &events, v_hardforks_t &hard_forks)
Definition: chaingen.cpp:966
void rct_config(rct::RCTConfig rct_config)
Definition: trezor_tests.h:94
void get_payments(const crypto::hash &payment_id, std::list< wallet2::payment_details > &payments, uint64_t min_height=0, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
Definition: wallet2.cpp:6320
void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key)
Definition: crypto.h:282
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
#define MTRACE(x)
Definition: misc_log_ex.h:77
bool init(const boost::program_options::variables_map &vm, const test_options *test_options=NULL, const GetCheckpointsCallback &get_checkpoints=nullptr)
initializes the core as needed
#define MINFO(x)
Definition: misc_log_ex.h:75
bool generate(std::vector< test_event_entry > &events) override
cryptonote::block m_head
Definition: trezor_tests.h:122
std::vector< cryptonote::tx_source_entry > m_sources
Definition: trezor_tests.h:194
Information representing errors in application but application will keep running. ...
virtual bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b)=0
bool set_module_name_and_folder(const std::string &path_to_process_)
Definition: string_tools.h:249
boost::optional< v_hardforks_t > hard_forks
Definition: chaingen.h:140
tsx_builder * compute_sources_to_sub_acc(boost::optional< size_t > num_utxo=boost::none, boost::optional< uint64_t > min_amount=boost::none, ssize_t offset=-1, int step=1, boost::optional< fnc_accept_tx_source_t > fnc_accept=boost::none)
std::vector< mgSig > MGs
Definition: rctTypes.h:321
std::vector< crypto::secret_key > additional_tx_keys
Definition: wallet2.h:473
std::vector< cryptonote::tx_destination_entry > dests
Definition: wallet2.h:474
virtual bool closeWallet(Wallet *wallet, bool store=true)=0
Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed...
bool generate(std::vector< test_event_entry > &events) override
virtual void add_shared_events(std::vector< test_event_entry > &events)
std::vector< size_t > m_selected_transfers
Definition: trezor_tests.h:193
::std::string string
Definition: gtest-port.h:1097
static subaddresses_t & get_subaddresses(tools::wallet2 *wallet)
Definition: wallet_tools.h:56
virtual void test_trezor_tx(std::vector< test_event_entry > &events, std::vector< tools::wallet2::pending_tx > &ptxs, std::vector< cryptonote::address_parse_info > &dsts_info, test_generator &generator, std::vector< tools::wallet2 *> wallets, bool is_sweep=false)
crypto::public_key pub_key
Definition: tx_extra.h:101
POD_CLASS key_derivation
Definition: crypto.h:98
static void set_account(tools::wallet2 *wallet, cryptonote::account_base &account)
void scalarmultKey(key &aP, const key &P, const key &a)
Definition: rctOps.cpp:368
block_tracker m_bt
Definition: trezor_tests.h:116
std::vector< size_t > selected_transfers
Definition: wallet2.h:470
void create_from_device(const std::string &device_name)
Definition: account.cpp:209
static const uint64_t m_wallet_ts
Definition: trezor_tests.h:102
#define ADD_HARDFORK(HARDFORKS, FORK, HEIGHT)
Definition: chaingen.h:799
static void init_options(boost::program_options::options_description &option_spec)
Definition: daemon.cpp:43
std::vector< std::string > tx_device_aux
Definition: device_cold.hpp:46
bool m_live_refresh_enabled
Definition: trezor_tests.h:129
#define MAKE_NEXT_BLOCK_TX_LIST_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST, HF)
Definition: chaingen.h:872
std::string mlog_get_default_log_path(const char *default_filename)
Definition: mlog.cpp:72
std::unordered_map< crypto::public_key, cryptonote::subaddress_index > subaddresses_t
Definition: chaingen.h:359
tsx_builder * sources(std::vector< cryptonote::tx_source_entry > &sources, std::vector< size_t > &selected_transfers)
uint64_t height
Definition: blockchain.cpp:91
bool generate(std::vector< test_event_entry > &events) override
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size=MAX_LOG_FILE_SIZE, const std::size_t max_log_files=MAX_LOG_FILES)
Definition: mlog.cpp:148
std::vector< cryptonote::tx_destination_entry > build_dsts(const var_addr_t &to1, bool sub1, uint64_t am1)
Definition: chaingen.cpp:813
std::string key_images
Definition: wallet2.h:471
boost::filesystem::path m_wallet_dir
Definition: trezor_tests.h:330
uint64_t sum_amount(const std::vector< tx_destination_entry > &destinations)
Definition: chaingen.cpp:700
uint64_t num_blocks(const std::vector< test_event_entry > &events)
Definition: chaingen.cpp:1044
std::unordered_set< size_t > m_integrated
Definition: trezor_tests.h:198
cryptonote::account_base m_alice_account
Definition: trezor_tests.h:133
std::vector< pending_tx > ptx
Definition: wallet2.h:505
std::string glob_to_regex(const std::string &val)
Definition: util.cpp:1012
cryptonote::tx_destination_entry change_dts
Definition: wallet2.h:423
#define REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT)
Definition: chaingen.h:889
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
#define TREZOR_TEST_SUFFIX()
gen_trezor_base * m_tester
Definition: trezor_tests.h:183
bool register_device(const std::string &device_name, device *hw_device)
Definition: device.cpp:100
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
tsx_builder * compute_sources_to_sub(boost::optional< size_t > num_utxo=boost::none, boost::optional< uint64_t > min_amount=boost::none, ssize_t offset=-1, int step=1, boost::optional< fnc_accept_tx_source_t > fnc_accept=boost::none)
const arg_descriptor< bool > arg_help
#define TESTS_DEFAULT_FEE
Definition: chaingen.h:1061
bool generate(std::vector< test_event_entry > &events) override
uint64_t m_cur_height
Definition: trezor_tests.h:184
boost::variant< cryptonote::account_public_address, cryptonote::account_keys, cryptonote::account_base, cryptonote::tx_destination_entry > var_addr_t
Definition: chaingen.h:362
unsigned char uint8_t
Definition: stdint.h:124
virtual void setup_args(const std::string &trezor_path, bool heavy_tests=false)
bool generate(std::vector< test_event_entry > &events) override
boost::variant< cryptonote::block, cryptonote::transaction, std::vector< cryptonote::transaction >, cryptonote::account_base, callback_entry, serialized_block, serialized_transaction, event_visitor_settings, event_replay_settings > test_event_entry
Definition: chaingen.h:162
crypto::secret_key generate(const crypto::secret_key &recovery_key=crypto::secret_key(), bool recover=false, bool two_random=false)
Definition: account.cpp:158
Level
Represents enumeration for severity level used to determine level of logging.
uint8_t m_top_hard_fork
Definition: trezor_tests.h:120
#define MAKE_TX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition: chaingen.h:933
cryptonote::tx_destination_entry build_dst(const var_addr_t &to, bool is_subaddr, uint64_t amount)
Definition: chaingen.cpp:804
cryptonote::block head_block() const
Definition: trezor_tests.h:92
#define REWIND_BLOCKS_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, HF)
Definition: chaingen.h:891
virtual void set_batch_transactions(bool)=0
sets whether or not to batch transactions
void get_payments_out(std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &confirmed_payments, uint64_t min_height, uint64_t max_height=(uint64_t) -1, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
Definition: wallet2.cpp:6346
#define HW_TREZOR_NAME
void copy(key &AA, const key &A)
Definition: rctOps.h:79
static const std::string m_alice_view_private
Definition: trezor_tests.h:107
virtual void test_get_tx(std::vector< test_event_entry > &events, std::vector< tools::wallet2 *> wallets, const std::vector< tools::wallet2::pending_tx > &ptxs, const std::vector< std::string > &aux_tx_info)
WalletManager - provides functions to manage wallets.
Definition: wallet2_api.h:1017
std::string m_trezor_path
Definition: trezor_tests.h:125
std::vector< uint8_t > extra
bool generate(std::vector< test_event_entry > &events) override
std::vector< cryptonote::tx_destination_entry > m_destinations
Definition: trezor_tests.h:195
void random32_unbiased(unsigned char *bytes)
Definition: crypto.cpp:110
tools::wallet2::unsigned_tx_set unsigned_tx_set
Definition: protocol.hpp:157
#define TREZOR_TEST_PREFIX()
std::vector< cryptonote::tx_source_entry > sources
Definition: wallet2.h:422
int main(int argc, char *argv[])
#define MDEBUG(x)
Definition: misc_log_ex.h:76
const account_keys & get_keys() const
Definition: account.cpp:264
virtual ~wallet_api_tests()
bool generate(std::vector< test_event_entry > &events) override
bool on_startup()
Definition: util.cpp:778
#define TREZOR_ACCOUNT_ORDERING
bool heavy_tests() const
Definition: trezor_tests.h:93
std::vector< tx_construction_data > txes
Definition: wallet2.h:499
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
cryptonote::account_base m_miner_account
Definition: trezor_tests.h:131
bool generate(std::vector< test_event_entry > &events) override
void tx_sign(hw::wallet_shim *wallet, const ::tools::wallet2::unsigned_tx_set &unsigned_tx, size_t idx, hw::tx_aux_data &aux_data, std::shared_ptr< hw::trezor::protocol::tx::Signer > &signer) override
std::vector< cryptonote::tx_destination_entry > m_destinations_orig
Definition: trezor_tests.h:196
const char *const ELECTRONEUM_VERSION_FULL
bool flush_txes_from_pool(const std::vector< crypto::hash > &txids)
remove transactions from the transaction pool (if present)
#define MGINFO_GREEN(x)
Definition: misc_log_ex.h:82
std::unique_ptr< tools::wallet2 > m_wl_bob
Definition: trezor_tests.h:137
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index &index) const
Definition: wallet2.cpp:1430
bool construct_tx_to_key(const std::vector< test_event_entry > &events, cryptonote::transaction &tx, const cryptonote::block &blk_head, const cryptonote::account_base &from, const var_addr_t &to, uint64_t amount, uint64_t fee, size_t nmix, bool rct, rct::RangeProofType range_proof_type, int bp_version)
Definition: chaingen.cpp:872
std::vector< transfer_details > transfer_container
Definition: wallet2.h:449
virtual void fork(gen_trezor_base &other)
tsx_builder * construct_pending_tx(tools::wallet2::pending_tx &ptx, boost::optional< std::vector< uint8_t >> extra=boost::none)
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
virtual void update_trackers(std::vector< test_event_entry > &events)
void setup_for_tests(const std::string &trezor_path, const std::string &seed, cryptonote::network_type network_type)
rctSigPrunable p
Definition: rctTypes.h:437
bool handle_error_helper(const boost::program_options::options_description &desc, F parser)
Definition: command_line.h:237
static WalletManager * getWalletManager()
#define TRY_ENTRY()
Definition: misc_log_ex.h:151
virtual Wallet * createWalletFromDevice(const std::string &path, const std::string &password, NetworkType nettype, const std::string &deviceName, uint64_t restoreHeight=0, const std::string &subaddressLookahead="", uint64_t kdf_rounds=1, WalletListener *listener=nullptr)=0
creates wallet using hardware device.
unsigned int uint32_t
Definition: stdint.h:126
tools::wallet2 * m_from
Definition: trezor_tests.h:190
std::function< bool(const tx_source_info_crate_t &info, bool &abort)> fnc_accept_tx_source_t
Definition: wallet_tools.h:48
struct hw::wallet_shim wallet_shim
virtual void init_fields()
std::pair< size_t, wallet2::transfer_container > transfers
Definition: wallet2.h:500
std::set< uint32_t > subaddr_indices
Definition: wallet2.h:432
bool get_block_hash(const block &b, crypto::hash &res)
bool generate(std::vector< test_event_entry > &events) override
#define TREZOR_TEST_MIXIN
Definition: trezor_tests.h:40
void get_blockchain_top(uint64_t &height, crypto::hash &top_id) const
get the hash and height of the most recent block
void fill_tx_destinations(const var_addr_t &from, const std::vector< tx_destination_entry > &dests, uint64_t fee, const std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, bool always_change)
Definition: chaingen.cpp:720
v_hardforks_t m_hard_forks
Definition: trezor_tests.h:121
bool generate(std::vector< test_event_entry > &events) override
device & get_device(const std::string &device_descriptor)
Definition: device.cpp:95
std::string const GENESIS_TX
bool generate(std::vector< test_event_entry > &events) override
bool get_short_payment_id(crypto::hash8 &payment_id8, const tools::wallet2::pending_tx &ptx, hw::device &hwdev)
virtual void add_transactions_to_events(std::vector< test_event_entry > &events, test_generator &generator, const std::vector< cryptonote::transaction > &txs)
static const std::string m_alice_spend_private
Definition: trezor_tests.h:106
#define CATCH_REPLAY(genclass)
Definition: chaingen.h:973
handles core cryptonote functionality
virtual void fix_hf(std::vector< test_event_entry > &events)
std::string obj_to_json_str(T &obj)
#define TREZOR_SKIP_IF_VERSION_LEQ(x)
unsigned __int64 uint64_t
Definition: stdint.h:136
std::vector< cryptonote::tx_destination_entry > splitted_dsts
Definition: wallet2.h:424
std::vector< multisig_sig > multisig_sigs
Definition: wallet2.h:475
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
Definition: device.hpp:210
static void build_options(boost::program_options::variables_map &vm, const boost::program_options::options_description &desc_params)
Definition: tools.cpp:48
#define TREZOR_TEST_FEE
Definition: trezor_tests.h:39
std::string dump_data(const cryptonote::transaction &tx)
Definition: chaingen.cpp:617
bool get_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash &payment_id)
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
cryptonote::transaction_prefix m_tx
Definition: wallet2.h:304
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) override
rct::RCTConfig m_rct_config
Definition: trezor_tests.h:200
static const std::string m_device_name
Definition: trezor_tests.h:103
size_t m_mixin
Definition: trezor_tests.h:188
#define TREZOR_TEST_PAYMENT_ID_LONG
Transaction-like interface for sending etn.
Definition: wallet2_api.h:72
std::vector< uint8_t > extra
Definition: wallet2.h:426
void set_createtime(uint64_t val)
Definition: account.h:96
crypto::hash head_hash() const
Definition: trezor_tests.h:91
tx_construction_data construction_data
Definition: wallet2.h:477
#define MAKE_TX_LIST_START(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition: chaingen.h:935
static const std::string m_device_seed
Definition: trezor_tests.h:105
cryptonote::account_public_address get_address(const var_addr_t &inp)
Definition: chaingen.cpp:665
POD_CLASS public_key
Definition: crypto.h:76
uint32_t m_account
Definition: trezor_tests.h:191
#define MWARNING(x)
Definition: misc_log_ex.h:74
void do_serialize(boost::mpl::false_, Archive &a, epee::net_utils::network_address &na)
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash8 &payment_id)
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
Definition: command_line.h:188
const BlockchainDB & get_db() const
get a reference to the BlockchainDB in use by Blockchain
Definition: blockchain.h:963
bool get_transactions(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
hw::trezor::device_trezor * m_trezor
Definition: trezor_tests.h:135
crypto::secret_key m_view_secret_key
Definition: account.h:45
uint64_t pack_version(uint32_t major, uint32_t minor, uint32_t patch)
Definition: transport.cpp:90
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
size_t m_compute_key_image_ctr
Definition: trezor_tests.h:207
std::vector< tools::wallet2::pending_tx > build()
static void process_transactions(tools::wallet2 *wallet, const std::vector< test_event_entry > &events, const cryptonote::block &blk_head, block_tracker &bt, const boost::optional< crypto::hash > &blk_tail=boost::none)
std::string m_payment_id
Definition: trezor_tests.h:199
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block&#39;s hash given a height
Definition: blockchain.cpp:901
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
static const std::string m_master_seed_str
Definition: trezor_tests.h:104
virtual void rewind_blocks(std::vector< test_event_entry > &events, size_t rewind_n, uint8_t hf)
account_public_address m_account_address
Definition: account.h:43
#define TREZOR_COMMON_TEST_CASE(genclass, CORE, BASE)
Mainly useful to represent current progress of application.
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
POD_CLASS hash8
Definition: hash.h:53
Blockchain & get_blockchain_storage()
gets the Blockchain instance
virtual bool generate(std::vector< test_event_entry > &events)
#define REWIND_BLOCKS(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC)
Definition: chaingen.h:890
std::unique_ptr< tools::wallet2 > m_wl_eve
Definition: trezor_tests.h:138
std::vector< test_event_entry > m_events
Definition: trezor_tests.h:123
std::shared_ptr< mock_daemon > m_daemon
Definition: trezor_tests.h:118
cryptonote::account_base m_bob_account
Definition: trezor_tests.h:132
test_generator m_generator
Definition: trezor_tests.h:115
std::shared_ptr< mock_daemon > daemon() const
Definition: trezor_tests.h:97
std::vector< cryptonote::address_parse_info > m_dsts_info
Definition: trezor_tests.h:197
POD_CLASS key_image
Definition: crypto.h:102
#define TREZOR_TEST_PAYMENT_ID
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void * memcpy(void *a, const void *b, size_t c)
static void default_options(boost::program_options::variables_map &vm)
Definition: daemon.cpp:53
std::vector< cryptonote::tx_destination_entry > dests
Definition: wallet2.h:430
crypto::secret_key m_spend_secret_key
Definition: account.h:44
bool generate(std::vector< test_event_entry > &events) override
#define DEFAULT_HARDFORKS(HARDFORKS)
Definition: chaingen.h:795
crypto::hash get_transaction_hash(const transaction &t)
bool remove_field_from_tx_extra(std::vector< uint8_t > &tx_extra, const std::type_info &type)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:271
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
boost::program_options::basic_parsed_options< charT > parse_command_line(int argc, const charT *const argv[], const boost::program_options::options_description &desc, bool allow_unregistered=false)
Definition: command_line.h:224
#define MAKE_TX_MIX_DEST_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, NMIX, HEAD)
Definition: chaingen.h:923
struct rule_list head
crypto::key_image m_key_image
Definition: wallet2.h:311
bool verRctNonSemanticsSimple(const rctSig &rv)
Definition: rctSigs.cpp:1085
uint32_t const GENESIS_NONCE
const cryptonote::test_options test_options
Definition: chaingen.h:699
virtual void setup_trezor()
std::vector< tools::wallet2::pending_tx > m_ptxs
Definition: trezor_tests.h:185
virtual crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index)=0
virtual void clear()
#define TREZOR_SETUP_CHAIN(NAME)
bool generate(std::vector< test_event_entry > &events) override
crypto::hash get_block_hash(uint64_t height)
boost::optional< int > bp_version
Definition: device_cold.hpp:48
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
virtual void update_client_settings()
cryptonote::tx_destination_entry change_dts
Definition: wallet2.h:469
crypto::secret_key tx_key
Definition: wallet2.h:472
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
Definition: blockchain.cpp:928
std::vector< cryptonote::address_parse_info > tx_recipients
Definition: device_cold.hpp:47
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
std::string to_string(t_connection_type type)
#define MK_COINS(amount)
Definition: chaingen.h:1060
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
bool generate(std::vector< test_event_entry > &events) override
static const uint64_t m_ts_start
Definition: trezor_tests.h:101
tsx_builder * destinations(std::vector< cryptonote::tx_destination_entry > &dsts)
cryptonote::account_base m_eve_account
Definition: trezor_tests.h:134
uint64_t m_fee
Definition: trezor_tests.h:189
cryptonote::block get_head_block(const std::vector< test_event_entry > &events)
Definition: chaingen.cpp:1058
#define MAKE_TX_LIST_START_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD)
Definition: chaingen.h:939
const std::pair< uint8_t, uint64_t > * hard_forks
void get(std::istream &input, bool &res)
Definition: io.h:62
bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, const std::vector< uint8_t > &extra, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, const uint32_t account_major_offset, const cryptonote::network_type nettype)
static tools::wallet2::transfer_container & get_transfers(tools::wallet2 *wallet)
Definition: wallet_tools.h:55
tsx_builder * compute_sources(boost::optional< size_t > num_utxo=boost::none, boost::optional< uint64_t > min_amount=boost::none, ssize_t offset=-1, int step=1, boost::optional< fnc_accept_tx_source_t > fnc_accept=boost::none)
#define MAKE_TX_MIX_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD)
Definition: chaingen.h:913
#define CATCH_ENTRY_L0(lacation, return_val)
Definition: misc_log_ex.h:165
tsx_builder * add_destination(const cryptonote::tx_destination_entry &dst)
void mlog_set_log_level(int level)
Definition: mlog.cpp:282
tsx_builder * build_tx()
static bool fill_tx_sources(tools::wallet2 *wallet, std::vector< cryptonote::tx_source_entry > &sources, size_t mixin, const boost::optional< size_t > &num_utxo, const boost::optional< uint64_t > &min_amount, block_tracker &bt, std::vector< size_t > &selected, uint64_t cur_height, ssize_t offset=0, int step=1, const boost::optional< fnc_accept_tx_source_t > &fnc_accept=boost::none)
#define MAKE_NEXT_BLOCK_TX_LIST(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST)
Definition: chaingen.h:867
std::unique_ptr< tools::wallet2 > m_wl_alice
Definition: trezor_tests.h:136
virtual void load(std::vector< test_event_entry > &events)
tsx_builder * set_integrated(size_t idx)
bool verRctSemanticsSimple(const std::vector< const rctSig *> &rvv)
Definition: rctSigs.cpp:975
uint64_t get_block_height(const block &b)
virtual void set_hard_fork(uint8_t hf)
std::vector< std::pair< uint8_t, uint64_t > > v_hardforks_t
Definition: chaingen.h:137
std::vector< size_t > selected_transfers
Definition: wallet2.h:425
tsx_builder * clear_current()
#define MAKE_NEXT_BLOCK_TX1_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TX1, HF)
Definition: chaingen.h:858
virtual void mine_and_test(std::vector< test_event_entry > &events)
void get_transfers(wallet2::transfer_container &incoming_transfers) const
Definition: wallet2.cpp:6315
cryptonote::network_type nettype() const
Definition: trezor_tests.h:96
#define MLOG(level, x)
Definition: misc_log_ex.h:78
#define REWIND_BLOCKS_N_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT, HF)
Definition: chaingen.h:877
bool get_pool_transaction_hashes(std::vector< crypto::hash > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool