Electroneum
Loading...
Searching...
No Matches
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
38using 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"
47
48
49namespace po = boost::program_options;
50
51namespace
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
82static device_trezor_test *trezor_device = nullptr;
83static device_trezor_test *ensure_trezor_test_device();
84static void rollback_chain(cryptonote::core * core, const cryptonote::block & head);
85static 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
87static 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
92int 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);
175 TREZOR_SETUP_CHAIN(std::string("HF") + std::to_string((int)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
229static 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
251static 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
275static 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
299template<class t_test_class>
300static 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
328static 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
384static 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
392static 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
399static 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
408static 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
425static 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
450static 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
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
472static 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
497static 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
505static 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
513static 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
536static 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
550static 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
571static 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
587static 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
600const uint64_t gen_trezor_base::m_ts_start = 1397862000; // As default wallet timestamp is 1397516400
601const uint64_t gen_trezor_base::m_wallet_ts = m_ts_start - 60*60*24*4;
602const std::string gen_trezor_base::m_device_name = "Trezor:udp";
603const std::string gen_trezor_base::m_master_seed_str = "14821d0bc5659b24cafbc889dc4fc60785ee08b65d71c525f81eeaba4f3a570f";
604const 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";
605const std::string gen_trezor_base::m_alice_spend_private = m_master_seed_str;
606const std::string gen_trezor_base::m_alice_view_private = "a6ccd4ac344a295d1387f8d18c81bdd394f1845de84188e204514ef9370fd403";
607
613
623
624void 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
662
664{
667 m_events.clear();
668 m_hard_forks.clear();
669 m_trezor = nullptr;
670}
671
672void 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{
682 m_miner_account.generate();
684
685 crypto::secret_key master_seed{};
687
688 m_alice_account.generate(master_seed, true);
689 m_alice_account.set_createtime(m_wallet_ts);
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
700bool gen_trezor_base::generate(std::vector<test_event_entry>& events)
701{
702 init_fields();
703 setup_trezor();
704
707
708 m_alice_account.create_from_device(*m_trezor);
709 m_alice_account.set_createtime(m_wallet_ts);
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;
716 generate_genesis_block(blk_gen, get_config(m_network_type).GENESIS_TX, get_config(m_network_type).GENESIS_NONCE);
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
721 m_bob_account.generate();
722 m_eve_account.generate();
723 m_bob_account.set_createtime(m_wallet_ts);
724 m_eve_account.set_createtime(m_wallet_ts);
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
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);
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
861void 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
896 m_bob_account.set_createtime(m_wallet_ts);
897 m_eve_account.set_createtime(m_wallet_ts);
898
899 setup_trezor();
901 m_alice_account.create_from_device(*m_trezor);
902 m_alice_account.set_createtime(m_wallet_ts);
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
917void 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
929void 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
958void gen_trezor_base::update_trackers(std::vector<test_event_entry>& events)
959{
961}
962
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
1008void 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;
1028 hw::wallet_shim wallet_shim;
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;
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
1159bool gen_trezor_base::verify_tx_key(const ::crypto::secret_key & tx_priv, const ::crypto::public_key & tx_pub, const subaddresses_t & subs)
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;
1208 const ::crypto::hash tx_prefix_hash = cryptonote::get_transaction_prefix_hash(c_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
1231void gen_trezor_base::mine_and_test(std::vector<test_event_entry>& events)
1232{
1234 const uint64_t height_before_mining = daemon()->get_height();
1235
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
1286tsx_builder * tsx_builder::sources(std::vector<cryptonote::tx_source_entry> & sources, std::vector<size_t> & selected_transfers)
1287{
1289 m_selected_transfers = selected_transfers;
1290 return this;
1291}
1292
1293tsx_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
1318tsx_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
1333tsx_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
1348tsx_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
1360tsx_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
1366tsx_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);
1406 fill_tx_destinations(m_from->get_subaddress({m_account, 0}), m_destinations_orig, m_fee, m_sources, m_destinations, true);
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
1427tsx_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
1467 for(uint32_t i = 0; i < 20; ++i)
1468 ptx.construction_data.subaddr_indices.insert(i);
1469
1470 return this;
1471}
1472
1473std::vector<tools::wallet2::pending_tx> tsx_builder::build()
1474{
1475 return m_ptxs;
1476}
1477
1479
1484
1485void device_trezor_test::setup_for_tests(const std::string & trezor_path, const std::string & seed, cryptonote::network_type network_type){
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
1502bool 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
1513void
1514device_trezor_test::tx_sign(hw::wallet_shim *wallet, const ::tools::wallet2::unsigned_tx_set &unsigned_tx, size_t idx,
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
1520bool 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;
1530 hw::wallet_shim wallet_shim;
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
1556bool gen_trezor_ki_sync_with_refresh::generate(std::vector<test_event_entry>& events)
1557{
1559 return gen_trezor_ki_sync::generate(events);
1560}
1561
1562bool 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
1568bool 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;
1600 ::crypto::derive_secret_key(D, i, m_alice_account.get_keys().m_spend_secret_key, scalar_step1);
1601 if (i == 0)
1602 {
1603 scalar_step2 = scalar_step1;
1604 }
1605 else
1606 {
1607 ::crypto::secret_key subaddr_sk = sw_device.get_subaddress_secret_key(m_alice_account.get_keys().m_view_secret_key, subaddr);
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;
1616
1617 dev_cold->live_refresh(
1618 m_alice_account.get_keys().m_view_secret_key,
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
1634bool 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
1649bool 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
1666bool 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
1684bool 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
1700bool 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
1715bool 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)
1724 ->rct_config(m_rct_config)
1725 ->build_tx();
1726
1728}
1729
1730bool 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)
1739 ->rct_config(m_rct_config)
1740 ->build_tx();
1741
1743}
1744
1745bool 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)
1755 ->rct_config(m_rct_config)
1756 ->build_tx();
1757
1759}
1760
1761bool 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)
1772 ->rct_config(m_rct_config)
1773 ->build_tx();
1774
1776}
1777
1778bool 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)
1789 ->rct_config(m_rct_config)
1790 ->build_tx();
1791
1793}
1794
1795bool 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)
1810 ->rct_config(m_rct_config)
1811 ->build_tx();
1812
1814}
1815
1816bool 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
1852bool 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
int main()
uint64_t height
cryptonote::block get_head_block(const std::vector< test_event_entry > &events)
cryptonote::tx_destination_entry build_dst(const var_addr_t &to, bool is_subaddr, uint64_t amount)
Definition chaingen.cpp:804
std::vector< cryptonote::tx_destination_entry > build_dsts(const var_addr_t &to1, bool sub1, uint64_t am1)
Definition chaingen.cpp:813
uint64_t num_blocks(const std::vector< test_event_entry > &events)
uint64_t sum_amount(const std::vector< tx_destination_entry > &destinations)
Definition chaingen.cpp:700
cryptonote::account_public_address get_address(const var_addr_t &inp)
Definition chaingen.cpp:665
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
bool extract_hard_forks(const std::vector< test_event_entry > &events, v_hardforks_t &hard_forks)
Definition chaingen.cpp:966
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
std::string dump_data(const cryptonote::transaction &tx)
Definition chaingen.cpp:617
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
#define REWIND_BLOCKS(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC)
Definition chaingen.h:890
#define MAKE_TX_MIX_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD)
Definition chaingen.h:913
#define MAKE_TX_MIX_DEST_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, NMIX, HEAD)
Definition chaingen.h:923
#define MAKE_TX_LIST_START(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition chaingen.h:935
std::vector< std::pair< uint8_t, uint64_t > > v_hardforks_t
Definition chaingen.h:137
#define MAKE_NEXT_BLOCK_TX_LIST(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST)
Definition chaingen.h:867
#define DEFAULT_HARDFORKS(HARDFORKS)
Definition chaingen.h:795
std::unordered_map< crypto::public_key, cryptonote::subaddress_index > subaddresses_t
Definition chaingen.h:359
#define REWIND_BLOCKS_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, HF)
Definition chaingen.h:891
#define MAKE_NEXT_BLOCK_TX_LIST_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST, HF)
Definition chaingen.h:872
#define MAKE_TX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition chaingen.h:933
#define CATCH_REPLAY(genclass)
Definition chaingen.h:973
#define REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT)
Definition chaingen.h:889
boost::variant< cryptonote::account_public_address, cryptonote::account_keys, cryptonote::account_base, cryptonote::tx_destination_entry > var_addr_t
Definition chaingen.h:362
#define ADD_HARDFORK(HARDFORKS, FORK, HEIGHT)
Definition chaingen.h:799
#define MK_COINS(amount)
Definition chaingen.h:1060
#define TESTS_DEFAULT_FEE
Definition chaingen.h:1061
#define MAKE_NEXT_BLOCK_TX1_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TX1, HF)
Definition chaingen.h:858
#define MAKE_TX_LIST_START_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD)
Definition chaingen.h:939
#define REWIND_BLOCKS_N_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT, HF)
Definition chaingen.h:877
bool replay_events_through_core(cryptonote::core &cr, const std::vector< test_event_entry > &events, t_test_class &validator)
Definition chaingen.h:666
virtual void set_batch_transactions(bool)=0
sets whether or not to batch transactions
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block's hash given a height
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
const BlockchainDB & get_db() const
get a reference to the BlockchainDB in use by Blockchain
Definition blockchain.h:963
bool flush_txes_from_pool(const std::vector< crypto::hash > &txids)
remove transactions from the transaction pool (if present)
bool get_transactions(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
handles core cryptonote functionality
void get_blockchain_top(uint64_t &height, crypto::hash &top_id) const
get the hash and height of the most recent block
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
bool deinit()
performs safe shutdown steps for core and core components
Blockchain & get_blockchain_storage()
gets the Blockchain instance
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
size_t m_compute_key_image_ctr
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
void setup_for_tests(const std::string &trezor_path, const std::string &seed, cryptonote::network_type network_type)
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
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
std::vector< test_event_entry > m_events
cryptonote::account_base m_bob_account
virtual void setup_trezor()
virtual void update_client_settings()
std::shared_ptr< mock_daemon > daemon() const
std::string m_trezor_path
virtual void update_trackers(std::vector< test_event_entry > &events)
cryptonote::network_type m_network_type
block_tracker m_bt
uint8_t m_top_hard_fork
static const uint64_t m_wallet_ts
static const std::string m_alice_view_private
cryptonote::account_base m_alice_account
bool m_live_refresh_enabled
virtual void clear()
cryptonote::block m_head
virtual void load(std::vector< test_event_entry > &events)
static const std::string m_device_seed
test_generator m_generator
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)
virtual void add_transactions_to_events(std::vector< test_event_entry > &events, test_generator &generator, const std::vector< cryptonote::transaction > &txs)
virtual void set_hard_fork(uint8_t hf)
hw::trezor::device_trezor * m_trezor
v_hardforks_t m_hard_forks
cryptonote::account_base m_miner_account
virtual bool verify_tx_key(const ::crypto::secret_key &tx_priv, const ::crypto::public_key &tx_pub, const subaddresses_t &subs)
std::unique_ptr< tools::wallet2 > m_wl_bob
virtual void setup_args(const std::string &trezor_path, bool heavy_tests=false)
crypto::hash head_hash() const
void rct_config(rct::RCTConfig rct_config)
static const std::string m_alice_spend_private
virtual void mine_and_test(std::vector< test_event_entry > &events)
virtual void init_fields()
virtual void add_shared_events(std::vector< test_event_entry > &events)
cryptonote::account_base m_eve_account
virtual void rewind_blocks(std::vector< test_event_entry > &events, size_t rewind_n, uint8_t hf)
virtual bool generate(std::vector< test_event_entry > &events)
static const std::string m_master_seed_str
bool heavy_tests() const
std::unique_ptr< tools::wallet2 > m_wl_alice
virtual void test_setup(std::vector< test_event_entry > &events)
static const uint64_t m_ts_start
virtual void fork(gen_trezor_base &other)
rct::RCTConfig m_rct_config
std::shared_ptr< mock_daemon > m_daemon
cryptonote::network_type nettype() const
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)
static const std::string m_device_name
cryptonote::block head_block() const
std::unique_ptr< tools::wallet2 > m_wl_eve
virtual void fix_hf(std::vector< test_event_entry > &events)
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
bool generate(std::vector< test_event_entry > &events) override
virtual bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b)=0
virtual crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index)=0
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
Definition device.hpp:210
std::vector< std::string > tx_device_aux
boost::optional< int > bp_version
std::vector< cryptonote::address_parse_info > tx_recipients
uint64_t get_height()
Definition daemon.cpp:371
cryptonote::core * core() const
Definition daemon.h:153
void mine_blocks(size_t num_blocks, const std::string &miner_address)
Definition daemon.cpp:312
static void default_options(boost::program_options::variables_map &vm)
Definition daemon.cpp:53
static void init_options(boost::program_options::options_description &option_spec)
Definition daemon.cpp:43
static void build_options(boost::program_options::variables_map &vm, const boost::program_options::options_description &desc_params)
Definition tools.cpp:48
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 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
void get_transfers(wallet2::transfer_container &incoming_transfers) const
Definition wallet2.cpp:6315
std::vector< transfer_details > transfer_container
Definition wallet2.h:449
std::vector< cryptonote::tx_source_entry > m_sources
gen_trezor_base * m_tester
std::vector< cryptonote::tx_destination_entry > m_destinations_orig
tsx_builder * clear_current()
std::vector< tools::wallet2::pending_tx > build()
std::vector< tools::wallet2::pending_tx > m_ptxs
tsx_builder * destinations(std::vector< cryptonote::tx_destination_entry > &dsts)
std::vector< size_t > m_selected_transfers
tsx_builder * construct_pending_tx(tools::wallet2::pending_tx &ptx, boost::optional< std::vector< uint8_t > > extra=boost::none)
tsx_builder * build_tx()
std::vector< cryptonote::address_parse_info > m_dsts_info
tsx_builder * sources(std::vector< cryptonote::tx_source_entry > &sources, std::vector< size_t > &selected_transfers)
tsx_builder * add_destination(const cryptonote::tx_destination_entry &dst)
tsx_builder * set_integrated(size_t idx)
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)
uint64_t m_cur_height
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)
rct::RCTConfig m_rct_config
std::vector< cryptonote::tx_destination_entry > m_destinations
uint32_t m_account
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)
tools::wallet2 * m_from
std::unordered_set< size_t > m_integrated
uint64_t m_fee
std::string m_payment_id
static void set_account(tools::wallet2 *wallet, cryptonote::account_base &account)
static subaddresses_t & get_subaddresses(tools::wallet2 *wallet)
static tools::wallet2::transfer_container & get_transfers(tools::wallet2 *wallet)
boost::filesystem::path m_wallet_dir
virtual ~wallet_api_tests()
bool generate(std::vector< test_event_entry > &events) override
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)
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)
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
void * memcpy(void *a, const void *b, size_t c)
const char * res
void get(std::istream &input, bool &res)
Definition io.h:62
#define MERROR(x)
Definition misc_log_ex.h:73
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::string mlog_get_default_log_path(const char *default_filename)
Definition mlog.cpp:72
#define MWARNING(x)
Definition misc_log_ex.h:74
#define MGINFO_GREEN(x)
Definition misc_log_ex.h:82
#define MDEBUG(x)
Definition misc_log_ex.h:76
void mlog_set_log_level(int level)
Definition mlog.cpp:282
#define MLOG(level, x)
Definition misc_log_ex.h:78
#define CATCH_ENTRY_L0(lacation, return_val)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
#define MTRACE(x)
Definition misc_log_ex.h:77
#define MINFO(x)
Definition misc_log_ex.h:75
#define TRY_ENTRY()
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
const arg_descriptor< bool > arg_help
bool handle_error_helper(const boost::program_options::options_description &desc, F parser)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
POD_CLASS hash8
Definition hash.h:53
POD_CLASS key_derivation
Definition crypto.h:101
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
POD_CLASS public_key
Definition crypto.h:79
void random32_unbiased(unsigned char *bytes)
Definition crypto.cpp:110
POD_CLASS key_image
Definition crypto.h:105
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition crypto.h:262
POD_CLASS hash
Definition hash.h:50
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition crypto.h:324
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
std::string obj_to_json_str(T &obj)
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)
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash8 &payment_id)
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
bool get_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash &payment_id)
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
bool get_block_hash(const block &b, crypto::hash &res)
uint64_t get_block_height(const block &b)
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
crypto::hash get_transaction_hash(const transaction &t)
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
bool remove_field_from_tx_extra(std::vector< uint8_t > &tx_extra, const std::type_info &type)
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
const config_t & get_config(network_type nettype)
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
Level
Represents enumeration for severity level used to determine level of logging.
@ Info
Mainly useful to represent current progress of application.
@ Error
Information representing errors in application but application will keep running.
bool set_module_name_and_folder(const std::string &path_to_process_)
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
uint64_t pack_version(uint32_t major, uint32_t minor, uint32_t patch)
Definition transport.cpp:90
device & get_device(const std::string &device_descriptor)
Definition device.cpp:95
bool register_device(const std::string &device_name, device *hw_device)
Definition device.cpp:100
void scalarmultKey(key &aP, const key &P, const key &a)
Definition rctOps.cpp:368
@ RCTTypeFull
Definition rctTypes.h:230
@ RCTTypeSimple
Definition rctTypes.h:231
@ RCTTypeBulletproof2
Definition rctTypes.h:233
@ RCTTypeBulletproof
Definition rctTypes.h:232
bool verRctSemanticsSimple(const std::vector< const rctSig * > &rvv)
Definition rctSigs.cpp:975
bool verRctNonSemanticsSimple(const rctSig &rv)
Definition rctSigs.cpp:1085
@ RangeProofPaddedBulletproof
Definition rctTypes.h:235
std::string glob_to_regex(const std::string &val)
Definition util.cpp:1012
bool on_startup()
Definition util.cpp:778
struct rule_list head
crypto::hash get_block_hash(uint64_t height)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
bool do_serialize(Archive< false > &ar, std::vector< crypto::signature > &v)
Definition crypto.h:44
CXA_THROW_INFO_T * info
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
Transaction-like interface for sending etn.
Definition wallet2_api.h:73
static WalletManager * getWalletManager()
WalletManager - provides functions to manage wallets.
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.
virtual bool closeWallet(Wallet *wallet, bool store=true)=0
Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed,...
std::vector< crypto::hash > tx_hashes
const std::pair< uint8_t, uint64_t > * hard_forks
crypto::public_key pub_key
Definition tx_extra.h:102
boost::optional< v_hardforks_t > hard_forks
Definition chaingen.h:140
const cryptonote::test_options test_options
Definition chaingen.h:699
boost::function< crypto::public_key(const tools::wallet2::transfer_details &td)> get_tx_pub_key_from_received_outs
tx_construction_data construction_data
Definition wallet2.h:477
std::vector< size_t > selected_transfers
Definition wallet2.h:470
crypto::secret_key tx_key
Definition wallet2.h:472
std::vector< cryptonote::tx_destination_entry > dests
Definition wallet2.h:474
std::vector< multisig_sig > multisig_sigs
Definition wallet2.h:475
cryptonote::transaction tx
Definition wallet2.h:466
std::vector< crypto::secret_key > additional_tx_keys
Definition wallet2.h:473
cryptonote::tx_destination_entry change_dts
Definition wallet2.h:469
std::vector< pending_tx > ptx
Definition wallet2.h:505
crypto::key_image m_key_image
Definition wallet2.h:311
cryptonote::transaction_prefix m_tx
Definition wallet2.h:304
std::vector< uint8_t > extra
Definition wallet2.h:426
std::vector< cryptonote::tx_source_entry > sources
Definition wallet2.h:422
std::vector< cryptonote::tx_destination_entry > splitted_dsts
Definition wallet2.h:424
std::vector< cryptonote::tx_destination_entry > dests
Definition wallet2.h:430
std::vector< size_t > selected_transfers
Definition wallet2.h:425
std::set< uint32_t > subaddr_indices
Definition wallet2.h:432
cryptonote::tx_destination_entry change_dts
Definition wallet2.h:423
std::vector< tx_construction_data > txes
Definition wallet2.h:499
std::pair< size_t, wallet2::transfer_container > transfers
Definition wallet2.h:500
#define TREZOR_COMMON_TEST_CASE(genclass, CORE, BASE)
#define TREZOR_TEST_SUFFIX()
#define TREZOR_TEST_PAYMENT_ID_LONG
#define TREZOR_ACCOUNT_ORDERING
#define TREZOR_SETUP_CHAIN(NAME)
#define TREZOR_TEST_PREFIX()
#define HW_TREZOR_NAME
#define TREZOR_SKIP_IF_VERSION_LEQ(x)
#define TREZOR_TEST_PAYMENT_ID
bool get_short_payment_id(crypto::hash8 &payment_id8, const tools::wallet2::pending_tx &ptx, hw::device &hwdev)
#define TREZOR_TEST_FEE
#define TREZOR_TEST_MIXIN
const char *const ELECTRONEUM_RELEASE_NAME
const char *const ELECTRONEUM_VERSION_FULL
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
std::function< bool(const tx_source_info_crate_t &info, bool &abort)> fnc_accept_tx_source_t