Electroneum
Loading...
Searching...
No Matches
serialization.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31
32#include <cstring>
33#include <cstdint>
34#include <cstdio>
35#include <iostream>
36#include <vector>
37#include <boost/foreach.hpp>
41#include "ringct/rctSigs.h"
48#include "wallet/wallet2.h"
49#include "gtest/gtest.h"
50#include "unit_tests_utils.h"
51#include "device/device.hpp"
52using namespace std;
53using namespace crypto;
54
55struct Struct
56{
59 char blob[8];
60};
61
62template <class Archive>
63struct serializer<Archive, Struct>
64{
65 static bool serialize(Archive &ar, Struct &s) {
66 ar.begin_object();
67 ar.tag("a");
68 ar.serialize_int(s.a);
69 ar.tag("b");
70 ar.serialize_int(s.b);
71 ar.tag("blob");
72 ar.serialize_blob(s.blob, sizeof(s.blob));
73 ar.end_object();
74 return true;
75 }
76};
77
78struct Struct1
79{
80 vector<boost::variant<Struct, int32_t>> si;
81 vector<int16_t> vi;
82
84 FIELD(si)
85 FIELD(vi)
87 /*template <bool W, template <bool> class Archive>
88 bool do_serialize(Archive<W> &ar)
89 {
90 ar.begin_object();
91 ar.tag("si");
92 ::do_serialize(ar, si);
93 ar.tag("vi");
94 ::do_serialize(ar, vi);
95 ar.end_object();
96 }*/
97};
98
99struct Blob
100{
103
104 bool operator==(const Blob& rhs) const
105 {
106 return a == rhs.a;
107 }
108};
109
117
119
120bool try_parse(const string &blob)
121{
122 Struct1 s1;
123 return serialization::parse_binary(blob, s1);
124}
125
126TEST(Serialization, BinaryArchiveInts) {
127 uint64_t x = 0xff00000000, x1;
128
129 ostringstream oss;
130 binary_archive<true> oar(oss);
131 oar.serialize_int(x);
132 ASSERT_TRUE(oss.good());
133 ASSERT_EQ(8, oss.str().size());
134 ASSERT_EQ(string("\0\0\0\0\xff\0\0\0", 8), oss.str());
135
136 istringstream iss(oss.str());
137 binary_archive<false> iar(iss);
138 iar.serialize_int(x1);
139 ASSERT_EQ(8, iss.tellg());
140 ASSERT_TRUE(iss.good());
141
142 ASSERT_EQ(x, x1);
143}
144
145TEST(Serialization, BinaryArchiveVarInts) {
146 uint64_t x = 0xff00000000, x1;
147
148 ostringstream oss;
149 binary_archive<true> oar(oss);
150 oar.serialize_varint(x);
151 ASSERT_TRUE(oss.good());
152 ASSERT_EQ(6, oss.str().size());
153 ASSERT_EQ(string("\x80\x80\x80\x80\xF0\x1F", 6), oss.str());
154
155 istringstream iss(oss.str());
156 binary_archive<false> iar(iss);
157 iar.serialize_varint(x1);
158 ASSERT_TRUE(iss.good());
159 ASSERT_EQ(x, x1);
160}
161
162TEST(Serialization, Test1) {
163 ostringstream str;
164 binary_archive<true> ar(str);
165
166 Struct1 s1;
167 s1.si.push_back(0);
168 {
169 Struct s;
170 s.a = 5;
171 s.b = 65539;
172 std::memcpy(s.blob, "12345678", 8);
173 s1.si.push_back(s);
174 }
175 s1.si.push_back(1);
176 s1.vi.push_back(10);
177 s1.vi.push_back(22);
178
179 string blob;
181 ASSERT_TRUE(try_parse(blob));
182
183 ASSERT_EQ('\xE0', blob[6]);
184 blob[6] = '\xE1';
185 ASSERT_FALSE(try_parse(blob));
186 blob[6] = '\xE2';
187 ASSERT_FALSE(try_parse(blob));
188}
189
190TEST(Serialization, Overflow) {
191 Blob x = { 0xff00000000 };
192 Blob x1;
193
194 string blob;
196 ASSERT_EQ(sizeof(Blob), blob.size());
197
199 ASSERT_EQ(x, x1);
200
201 vector<Blob> bigvector;
203 ASSERT_EQ(0, bigvector.size());
204}
205
206TEST(Serialization, serializes_vector_uint64_as_varint)
207{
208 std::vector<uint64_t> v;
209 string blob;
210
212 ASSERT_EQ(1, blob.size());
213
214 // +1 byte
215 v.push_back(0);
217 ASSERT_EQ(2, blob.size());
218
219 // +1 byte
220 v.push_back(1);
222 ASSERT_EQ(3, blob.size());
223
224 // +2 bytes
225 v.push_back(0x80);
227 ASSERT_EQ(5, blob.size());
228
229 // +2 bytes
230 v.push_back(0xFF);
232 ASSERT_EQ(7, blob.size());
233
234 // +2 bytes
235 v.push_back(0x3FFF);
237 ASSERT_EQ(9, blob.size());
238
239 // +3 bytes
240 v.push_back(0x40FF);
242 ASSERT_EQ(12, blob.size());
243
244 // +10 bytes
245 v.push_back(0xFFFFFFFFFFFFFFFF);
247 ASSERT_EQ(22, blob.size());
248}
249
250TEST(Serialization, serializes_vector_int64_as_fixed_int)
251{
252 std::vector<int64_t> v;
253 string blob;
254
256 ASSERT_EQ(1, blob.size());
257
258 // +8 bytes
259 v.push_back(0);
261 ASSERT_EQ(9, blob.size());
262
263 // +8 bytes
264 v.push_back(1);
266 ASSERT_EQ(17, blob.size());
267
268 // +8 bytes
269 v.push_back(0x80);
271 ASSERT_EQ(25, blob.size());
272
273 // +8 bytes
274 v.push_back(0xFF);
276 ASSERT_EQ(33, blob.size());
277
278 // +8 bytes
279 v.push_back(0x3FFF);
281 ASSERT_EQ(41, blob.size());
282
283 // +8 bytes
284 v.push_back(0x40FF);
286 ASSERT_EQ(49, blob.size());
287
288 // +8 bytes
289 v.push_back(0xFFFFFFFFFFFFFFFF);
291 ASSERT_EQ(57, blob.size());
292}
293
294namespace
295{
296 template<typename T>
297 std::vector<T> linearize_vector2(const std::vector< std::vector<T> >& vec_vec)
298 {
299 std::vector<T> res;
300 BOOST_FOREACH(const auto& vec, vec_vec)
301 {
302 res.insert(res.end(), vec.begin(), vec.end());
303 }
304 return res;
305 }
306}
307
308TEST(Serialization, serializes_transacion_signatures_correctly)
309{
310 using namespace cryptonote;
311
312 transaction tx;
313 transaction tx1;
314 string blob;
315
316 // Empty tx
317 tx.set_null();
319 ASSERT_EQ(5, blob.size()); // 5 bytes + 0 bytes extra + 0 bytes signatures
321 ASSERT_EQ(tx, tx1);
322 ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures));
323
324 // Miner tx without signatures
325 txin_gen txin_gen1;
326 txin_gen1.height = 0;
327 tx.set_null();
328 tx.vin.push_back(txin_gen1);
330 ASSERT_EQ(7, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures
332 ASSERT_EQ(tx, tx1);
333 ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures));
334
335 // Miner tx with empty signatures 2nd vector
336 tx.signatures.resize(1);
339 ASSERT_EQ(7, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures
341 ASSERT_EQ(tx, tx1);
342 ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures));
343
344 // Miner tx with one signature
345 tx.signatures[0].resize(1);
347
348 // Miner tx with 2 empty vectors
349 tx.signatures.resize(2);
350 tx.signatures[0].resize(0);
351 tx.signatures[1].resize(0);
354
355 // Miner tx with 2 signatures
356 tx.signatures[0].resize(1);
357 tx.signatures[1].resize(1);
360
361 // Two txin_gen, no signatures
362 tx.vin.push_back(txin_gen1);
363 tx.signatures.resize(0);
366 ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
368 ASSERT_EQ(tx, tx1);
369 ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures));
370
371 // Two txin_gen, signatures vector contains only one empty element
372 tx.signatures.resize(1);
375
376 // Two txin_gen, signatures vector contains two empty elements
377 tx.signatures.resize(2);
380 ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
382 ASSERT_EQ(tx, tx1);
383 ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures));
384
385 // Two txin_gen, signatures vector contains three empty elements
386 tx.signatures.resize(3);
389
390 // Two txin_gen, signatures vector contains two non empty elements
391 tx.signatures.resize(2);
392 tx.signatures[0].resize(1);
393 tx.signatures[1].resize(1);
396
397 // A few bytes instead of signature
398 tx.vin.clear();
399 tx.vin.push_back(txin_gen1);
400 tx.signatures.clear();
403 blob.append(std::string(sizeof(crypto::signature) / 2, 'x'));
405
406 // blob contains one signature
407 blob.append(std::string(sizeof(crypto::signature) / 2, 'y'));
409
410 // Not enough signature vectors for all inputs
411 txin_to_key txin_to_key1;
412 txin_to_key1.amount = 1;
413 memset(&txin_to_key1.k_image, 0x42, sizeof(crypto::key_image));
414 txin_to_key1.key_offsets.push_back(12);
415 txin_to_key1.key_offsets.push_back(3453);
416 tx.vin.clear();
417 tx.vin.push_back(txin_to_key1);
418 tx.vin.push_back(txin_to_key1);
419 tx.signatures.resize(1);
420 tx.signatures[0].resize(2);
423
424 // Too much signatures for two inputs
425 tx.signatures.resize(3);
426 tx.signatures[0].resize(2);
427 tx.signatures[1].resize(2);
428 tx.signatures[2].resize(2);
431
432 // First signatures vector contains too little elements
433 tx.signatures.resize(2);
434 tx.signatures[0].resize(1);
435 tx.signatures[1].resize(2);
438
439 // First signatures vector contains too much elements
440 tx.signatures.resize(2);
441 tx.signatures[0].resize(3);
442 tx.signatures[1].resize(2);
445
446 // There are signatures for each input
447 tx.signatures.resize(2);
448 tx.signatures[0].resize(2);
449 tx.signatures[1].resize(2);
453 ASSERT_EQ(tx, tx1);
454 ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures));
455
456 // Blob doesn't contain enough data
457 blob.resize(blob.size() - sizeof(crypto::signature) / 2);
459
460 // Blob contains too much data
461 blob.resize(blob.size() + sizeof(crypto::signature));
463
464 // Blob contains one excess signature
465 blob.resize(blob.size() + sizeof(crypto::signature) / 2);
467}
468
469TEST(Serialization, serializes_ringct_types)
470{
471 string blob;
472 rct::key key0, key1;
473 rct::keyV keyv0, keyv1;
474 rct::keyM keym0, keym1;
475 rct::ctkey ctkey0, ctkey1;
476 rct::ctkeyV ctkeyv0, ctkeyv1;
477 rct::ctkeyM ctkeym0, ctkeym1;
478 rct::ecdhTuple ecdh0, ecdh1;
479 rct::boroSig boro0, boro1;
480 rct::mgSig mg0, mg1;
481 rct::Bulletproof bp0, bp1;
482 rct::rctSig s0, s1;
484
485 key0 = rct::skGen();
488 ASSERT_TRUE(key0 == key1);
489
490 keyv0 = rct::skvGen(30);
491 for (size_t n = 0; n < keyv0.size(); ++n)
492 keyv0[n] = rct::skGen();
495 ASSERT_TRUE(keyv0.size() == keyv1.size());
496 for (size_t n = 0; n < keyv0.size(); ++n)
497 {
498 ASSERT_TRUE(keyv0[n] == keyv1[n]);
499 }
500
501 keym0 = rct::keyMInit(9, 12);
502 for (size_t n = 0; n < keym0.size(); ++n)
503 for (size_t i = 0; i < keym0[n].size(); ++i)
504 keym0[n][i] = rct::skGen();
507 ASSERT_TRUE(keym0.size() == keym1.size());
508 for (size_t n = 0; n < keym0.size(); ++n)
509 {
510 ASSERT_TRUE(keym0[n].size() == keym1[n].size());
511 for (size_t i = 0; i < keym0[n].size(); ++i)
512 {
513 ASSERT_TRUE(keym0[n][i] == keym1[n][i]);
514 }
515 }
516
517 rct::skpkGen(ctkey0.dest, ctkey0.mask);
520 ASSERT_TRUE(!memcmp(&ctkey0, &ctkey1, sizeof(ctkey0)));
521
522 ctkeyv0 = std::vector<rct::ctkey>(14);
523 for (size_t n = 0; n < ctkeyv0.size(); ++n)
524 rct::skpkGen(ctkeyv0[n].dest, ctkeyv0[n].mask);
527 ASSERT_TRUE(ctkeyv0.size() == ctkeyv1.size());
528 for (size_t n = 0; n < ctkeyv0.size(); ++n)
529 {
530 ASSERT_TRUE(!memcmp(&ctkeyv0[n], &ctkeyv1[n], sizeof(ctkeyv0[n])));
531 }
532
533 ctkeym0 = std::vector<rct::ctkeyV>(9);
534 for (size_t n = 0; n < ctkeym0.size(); ++n)
535 {
536 ctkeym0[n] = std::vector<rct::ctkey>(11);
537 for (size_t i = 0; i < ctkeym0[n].size(); ++i)
538 rct::skpkGen(ctkeym0[n][i].dest, ctkeym0[n][i].mask);
539 }
542 ASSERT_TRUE(ctkeym0.size() == ctkeym1.size());
543 for (size_t n = 0; n < ctkeym0.size(); ++n)
544 {
545 ASSERT_TRUE(ctkeym0[n].size() == ctkeym1[n].size());
546 for (size_t i = 0; i < ctkeym0.size(); ++i)
547 {
548 ASSERT_TRUE(!memcmp(&ctkeym0[n][i], &ctkeym1[n][i], sizeof(ctkeym0[n][i])));
549 }
550 }
551
552 ecdh0.mask = rct::skGen();
553 ecdh0.amount = rct::skGen();
556 ASSERT_TRUE(!memcmp(&ecdh0.mask, &ecdh1.mask, sizeof(ecdh0.mask)));
557 ASSERT_TRUE(!memcmp(&ecdh0.amount, &ecdh1.amount, sizeof(ecdh0.amount)));
558
559 for (size_t n = 0; n < 64; ++n)
560 {
561 boro0.s0[n] = rct::skGen();
562 boro0.s1[n] = rct::skGen();
563 }
564 boro0.ee = rct::skGen();
567 ASSERT_TRUE(!memcmp(&boro0, &boro1, sizeof(boro0)));
568
569 // create a full rct signature to use its innards
570 vector<uint64_t> inamounts;
571 rct::ctkeyV sc, pc;
572 rct::ctkey sctmp, pctmp;
573 inamounts.push_back(6000);
574 tie(sctmp, pctmp) = rct::ctskpkGen(inamounts.back());
575 sc.push_back(sctmp);
576 pc.push_back(pctmp);
577 inamounts.push_back(7000);
578 tie(sctmp, pctmp) = rct::ctskpkGen(inamounts.back());
579 sc.push_back(sctmp);
580 pc.push_back(pctmp);
581 vector<uint64_t> amounts;
582 rct::keyV amount_keys;
583 //add output 500
584 amounts.push_back(500);
585 amount_keys.push_back(rct::hash_to_scalar(rct::zero()));
586 rct::keyV destinations;
587 rct::key Sk, Pk;
588 rct::skpkGen(Sk, Pk);
589 destinations.push_back(Pk);
590 //add output for 12500
591 amounts.push_back(12500);
592 amount_keys.push_back(rct::hash_to_scalar(rct::zero()));
593 rct::skpkGen(Sk, Pk);
594 destinations.push_back(Pk);
595 //compute rct data with mixin 3
597 s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default"));
598
599 mg0 = s0.p.MGs[0];
602 ASSERT_TRUE(mg0.ss.size() == mg1.ss.size());
603 for (size_t n = 0; n < mg0.ss.size(); ++n)
604 {
605 ASSERT_TRUE(mg0.ss[n] == mg1.ss[n]);
606 }
607 ASSERT_TRUE(mg0.cc == mg1.cc);
608
609 // mixRing and II are not serialized, they are meant to be reconstructed
610 ASSERT_TRUE(mg1.II.empty());
611
612 ASSERT_FALSE(s0.p.bulletproofs.empty());
613 bp0 = s0.p.bulletproofs.front();
616 bp1.V = bp0.V; // this is not saved, as it is reconstructed from other tx data
617 ASSERT_EQ(bp0, bp1);
618}
619
620// ToDo : Change this test to test features relevant to the Electroneum Project (Wallet needs creating and such)
621TEST(Serialization, portability_wallet)
622{
624 tools::wallet2 w(nettype);
625 const boost::filesystem::path wallet_file = unit_test::data_dir / "wallet_etnkA3";
626 string password = "test";
627 bool r = false;
628 try
629 {
630 w.load(wallet_file.string(), password);
631 r = true;
632 }
633 catch (const exception& e)
634 {}
635 ASSERT_TRUE(r);
636 /*
637 fields of tools::wallet2 to be checked:
638 std::vector<crypto::hash> m_blockchain
639 std::vector<transfer_details> m_transfers // TODO
640 cryptonote::account_public_address m_account_public_address
641 std::unordered_map<crypto::key_image, size_t> m_key_images
642 std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs
643 std::unordered_multimap<crypto::hash, payment_details> m_payments
644 std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys
645 std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs
646 std::unordered_map<crypto::hash, std::string> m_tx_notes
647 std::unordered_map<crypto::hash, payment_details> m_unconfirmed_payments
648 std::unordered_map<crypto::public_key, size_t> m_pub_keys
649
650 std::unordered_map<std::pair<crypto::hash, size_t>, size_t, m_chainstate_indexes
651 boost::hash<std::pair<crypto::hash, size_t>>>
652
653 std::vector<tools::wallet2::address_book_row> m_address_book
654 */
655 // blockchain
656 ASSERT_TRUE(w.m_blockchain.size() == 105);
657 ASSERT_TRUE(epee::string_tools::pod_to_hex(w.m_blockchain[0]) == "9070199e8ed5f151babde58284c1fa0fd4cd6478499adff4eb41884ccdc3e377");
658 // transfers (TODO)
659 ASSERT_TRUE(w.m_transfers.size() == 20);
660 // account public address
661 ASSERT_TRUE(epee::string_tools::pod_to_hex(w.m_account_public_address.m_view_public_key) == "5bb38f9514f70673e1d4e87242d8c2d0a99cb4aeae3cda282869c9de4ca7d71f");
662 ASSERT_TRUE(epee::string_tools::pod_to_hex(w.m_account_public_address.m_spend_public_key) == "7b0ca4ee4cf32ac393b0306402d71b2c4a3db02c45ffbb780c2fde677b03848d");
663 // key images
664 ASSERT_TRUE(w.m_key_images.size() == 20);
665 {
666 crypto::key_image ki[3];
667 epee::string_tools::hex_to_pod("461325ee51dbc9debaad955411287f08a39aa4e184afa25ba79d76525e32c27e", ki[0]);
668 epee::string_tools::hex_to_pod("3fe808aa18a71fa20b30f26d275278e5e284818200651f483e257b5e2b12b874", ki[1]);
669 epee::string_tools::hex_to_pod("5974a90353fb388d397f1deb900071d1c03f281ac341cadfa553040f3b937548", ki[2]);
670 ASSERT_EQ_MAP(0, w.m_key_images, ki[0]);
671 ASSERT_EQ_MAP(1, w.m_key_images, ki[1]);
672 ASSERT_EQ_MAP(2, w.m_key_images, ki[2]);
673 }
674 // unconfirmed txs
675 ASSERT_TRUE(w.m_unconfirmed_txs.size() == 0);
676 // payments
677 ASSERT_TRUE(w.m_payments.size() == 4);
678 {
679 auto pd0 = w.m_payments.begin();
680 auto pd1 = pd0;
681 ++pd1;
682 ASSERT_TRUE(epee::string_tools::pod_to_hex(pd0->first) == "0000000000000000000000000000000000000000000000000000000000000000");
683 ASSERT_TRUE(epee::string_tools::pod_to_hex(pd1->first) == "0000000000000000000000000000000000000000000000000000000000000000");
684 if (epee::string_tools::pod_to_hex(pd0->second.m_tx_hash) == "ec34c9bb12b99af33d49691384eee5bed9171498ff04e59516505f35d1fc5efc")
685 swap(pd0, pd1);
686 ASSERT_TRUE(epee::string_tools::pod_to_hex(pd0->second.m_tx_hash) == "c02c01691271e26da9c4dad4f30b270984c98b555d85528871dea60c453a0bdc");
687 ASSERT_TRUE(epee::string_tools::pod_to_hex(pd1->second.m_tx_hash) == "682e3af2997fc46222a4e8690ae628fcc9cf657e9b93d16c341d5ba622c39607");
688 ASSERT_TRUE(pd0->second.m_amount == 801071);
689 ASSERT_TRUE(pd1->second.m_amount == 801070);
690 ASSERT_TRUE(pd0->second.m_block_height == 19);
691 ASSERT_TRUE(pd1->second.m_block_height == 20);
692 ASSERT_TRUE(pd0->second.m_unlock_time == 37);
693 ASSERT_TRUE(pd1->second.m_unlock_time == 38);
694 ASSERT_TRUE(pd0->second.m_timestamp == 1529981363);
695 ASSERT_TRUE(pd1->second.m_timestamp == 1529981381);
696 }
697 // tx keys
698 ASSERT_TRUE(w.m_tx_keys.size() == 2);
699 {
700 const std::vector<std::pair<std::string, std::string>> txid_txkey =
701 {
702 {"ba1deb702d98d78f589ffda136031ef355c4b27213205653f0682abc73fd2069", "4fef24852171a1baa436975ad76f9c7fdba990fb3a817442eccf6e12d62cb200"},
703 {"d26df736b0a0f6946d8a05596848acd531d65d57926ac64b17f0c22611f3f437", "088732a6d90686d8999f03c8f9910c86edd6e1543e2611727a9502cbad2fa605"},
704 };
705 for (size_t i = 0; i < txid_txkey.size(); ++i)
706 {
707 crypto::hash txid;
708 crypto::secret_key txkey;
709 epee::string_tools::hex_to_pod(txid_txkey[i].first, txid);
710 epee::string_tools::hex_to_pod(txid_txkey[i].second, txkey);
711 ASSERT_EQ_MAP(txkey, w.m_tx_keys, txid);
712 }
713 }
714 // confirmed txs
715 ASSERT_TRUE(w.m_confirmed_txs.size() == 2);
716 // tx notes
717 ASSERT_TRUE(w.m_tx_notes.size() == 2);
718 {
719 crypto::hash h[2];
720 epee::string_tools::hex_to_pod("d26df736b0a0f6946d8a05596848acd531d65d57926ac64b17f0c22611f3f437", h[0]);
721 epee::string_tools::hex_to_pod("ba1deb702d98d78f589ffda136031ef355c4b27213205653f0682abc73fd2069", h[1]);
722 ASSERT_EQ_MAP("sample note", w.m_tx_notes, h[0]);
723 ASSERT_EQ_MAP("sample note 2", w.m_tx_notes, h[1]);
724 }
725 // unconfirmed payments
726 ASSERT_TRUE(w.m_unconfirmed_payments.size() == 0);
727 // pub keys
728 ASSERT_TRUE(w.m_pub_keys.size() == 20);
729 {
730 crypto::public_key pubkey[3];
731 epee::string_tools::hex_to_pod("11354e39cfe37df3173285f1d76624f940d721dfc81e2648638afa929ecbf997", pubkey[0]);
732 epee::string_tools::hex_to_pod("070a7f025c601dc44f8bd8de9ad162a91215b1618d658cece39a60a6aa29a2fd", pubkey[1]);
733 epee::string_tools::hex_to_pod("bb64979c04341600f963ec0c9a09855b7ae4dc8ba90ab6322313636fd42c11c7", pubkey[2]);
734 ASSERT_EQ_MAP(0, w.m_pub_keys, pubkey[0]);
735 ASSERT_EQ_MAP(1, w.m_pub_keys, pubkey[1]);
736 ASSERT_EQ_MAP(2, w.m_pub_keys, pubkey[2]);
737 }
738 // address book
739 ASSERT_TRUE(w.m_address_book.size() == 1);
740 {
741 auto address_book_row = w.m_address_book.begin();
742 ASSERT_TRUE(epee::string_tools::pod_to_hex(address_book_row->m_address.m_spend_public_key) == "7d996b0f2db6dbb5f2a086211f2399a4a7479b2c911af307fdc3f7f61a88cb0e");
743 ASSERT_TRUE(epee::string_tools::pod_to_hex(address_book_row->m_address.m_view_public_key) == "1c06bcac7082f73af10460b5f2849aded79374b2fbdaae5d9384b9b6514fddcb");
744 ASSERT_TRUE(epee::string_tools::pod_to_hex(address_book_row->m_payment_id) == "393d7376d934a9a9000000000000000000000000000000000000000000000000");
745 ASSERT_TRUE(address_book_row->m_description == "testnet etn wallet");
746 }
747}
748
749// ToDo : Change this test to test features relevant to the Electroneum Project (Wallet needs creating and such)
750#define OUTPUT_EXPORT_FILE_MAGIC "Electroneum output export\003"
751TEST(Serialization, portability_outputs)
752{
753 // read file
754 const boost::filesystem::path filename = unit_test::data_dir / "outputs_etnkA3";
755 std::string data;
756 bool r = epee::file_io_utils::load_file_to_string(filename.string(), data);
757 ASSERT_TRUE(r);
758 const size_t magiclen = strlen(OUTPUT_EXPORT_FILE_MAGIC);
759 ASSERT_FALSE(data.size() < magiclen || memcmp(data.data(), OUTPUT_EXPORT_FILE_MAGIC, magiclen));
760 // decrypt (copied from wallet2::decrypt)
761 auto decrypt = [] (const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated) -> string
762 {
763 const size_t prefix_size = sizeof(chacha_iv) + (authenticated ? sizeof(crypto::signature) : 0);
764 if(ciphertext.size() < prefix_size)
765 return {};
766 crypto::chacha_key key;
767 crypto::generate_chacha_key(&skey, sizeof(skey), key, 1);
768 const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
769 std::string plaintext;
770 plaintext.resize(ciphertext.size() - prefix_size);
771 if (authenticated)
772 {
774 crypto::cn_fast_hash(ciphertext.data(), ciphertext.size() - sizeof(signature), hash);
777 const crypto::signature &signature = *(const crypto::signature*)&ciphertext[ciphertext.size() - sizeof(crypto::signature)];
779 return {};
780 }
781 crypto::chacha8(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, &plaintext[0]);
782 return plaintext;
783 };
784 crypto::secret_key view_secret_key;
785 epee::string_tools::hex_to_pod("f747f4a4838027c9af80e6364a941b60c538e67e9ea198b6ec452b74c276de06", view_secret_key);
786 bool authenticated = true;
787 data = decrypt(std::string(data, magiclen), view_secret_key, authenticated);
788 ASSERT_FALSE(data.empty());
789 // check public view/spend keys
790 const size_t headerlen = 2 * sizeof(crypto::public_key);
791 ASSERT_FALSE(data.size() < headerlen);
792 const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[0];
793 const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[sizeof(crypto::public_key)];
794 ASSERT_TRUE(epee::string_tools::pod_to_hex(public_spend_key) == "7b0ca4ee4cf32ac393b0306402d71b2c4a3db02c45ffbb780c2fde677b03848d");
795 ASSERT_TRUE(epee::string_tools::pod_to_hex(public_view_key) == "5bb38f9514f70673e1d4e87242d8c2d0a99cb4aeae3cda282869c9de4ca7d71f");
796 r = false;
797 std::vector<tools::wallet2::transfer_details> outputs;
798 try
799 {
800 std::istringstream iss(std::string(data, headerlen));
802 ar >> outputs;
803 r = true;
804 }
805 catch (...)
806 {}
807 ASSERT_TRUE(r);
808 /*
809 fields of tools::wallet2::transfer_details to be checked:
810 uint64_t m_block_height
811 cryptonote::transaction_prefix m_tx // TODO
812 crypto::hash m_txid
813 size_t m_internal_output_index
814 uint64_t m_global_output_index
815 bool m_spent
816 uint64_t m_spent_height
817 crypto::key_image m_key_image
818 rct::key m_mask
819 uint64_t m_amount
820 bool m_rct
821 bool m_key_image_known
822 size_t m_pk_index
823 */
824 ASSERT_EQ(outputs.size(), 20);
825 auto& td0 = outputs[0];
826 auto& td1 = outputs[1];
827 auto& td2 = outputs[2];
828 ASSERT_EQ(td0.m_block_height, 19);
829 ASSERT_EQ(td1.m_block_height, 19);
830 ASSERT_EQ(td2.m_block_height, 19);
831 ASSERT_EQ(epee::string_tools::pod_to_hex(td0.m_txid), "c02c01691271e26da9c4dad4f30b270984c98b555d85528871dea60c453a0bdc");
832 ASSERT_EQ(epee::string_tools::pod_to_hex(td1.m_txid), "c02c01691271e26da9c4dad4f30b270984c98b555d85528871dea60c453a0bdc");
833 ASSERT_EQ(epee::string_tools::pod_to_hex(td2.m_txid), "c02c01691271e26da9c4dad4f30b270984c98b555d85528871dea60c453a0bdc");
834 ASSERT_EQ(td0.m_internal_output_index, 0);
835 ASSERT_EQ(td1.m_internal_output_index, 1);
836 ASSERT_EQ(td2.m_internal_output_index, 2);
837 ASSERT_EQ(td0.m_global_output_index, 1);
838 ASSERT_EQ(td1.m_global_output_index, 11);
839 ASSERT_EQ(td2.m_global_output_index, 17);
840 ASSERT_FALSE(td0.m_spent);
841 ASSERT_TRUE(td1.m_spent);
842 ASSERT_FALSE(td2.m_spent);
843 ASSERT_EQ(td0.m_spent_height, 0);
844 ASSERT_EQ(td1.m_spent_height, 101);
845 ASSERT_EQ(td2.m_spent_height, 0);
846 ASSERT_EQ(epee::string_tools::pod_to_hex(td0.m_key_image), "461325ee51dbc9debaad955411287f08a39aa4e184afa25ba79d76525e32c27e");
847 ASSERT_EQ(epee::string_tools::pod_to_hex(td1.m_key_image), "3fe808aa18a71fa20b30f26d275278e5e284818200651f483e257b5e2b12b874");
848 ASSERT_EQ(epee::string_tools::pod_to_hex(td2.m_key_image), "5974a90353fb388d397f1deb900071d1c03f281ac341cadfa553040f3b937548");
849 ASSERT_EQ(epee::string_tools::pod_to_hex(td0.m_mask), "0100000000000000000000000000000000000000000000000000000000000000");
850 ASSERT_EQ(epee::string_tools::pod_to_hex(td1.m_mask), "0100000000000000000000000000000000000000000000000000000000000000");
851 ASSERT_EQ(epee::string_tools::pod_to_hex(td2.m_mask), "0100000000000000000000000000000000000000000000000000000000000000");
852 ASSERT_EQ(td0.m_amount, 1);
853 ASSERT_EQ(td1.m_amount, 70);
854 ASSERT_EQ(td2.m_amount, 1000);
855 ASSERT_FALSE(td0.m_rct);
856 ASSERT_FALSE(td1.m_rct);
857 ASSERT_FALSE(td2.m_rct);
858 ASSERT_TRUE(td0.m_key_image_known);
859 ASSERT_TRUE(td1.m_key_image_known);
860 ASSERT_TRUE(td2.m_key_image_known);
861 ASSERT_EQ(td0.m_pk_index, 0);
862 ASSERT_EQ(td1.m_pk_index, 0);
863 ASSERT_EQ(td2.m_pk_index, 0);
864}
865
867{
868 std::vector<tools::wallet2::tx_construction_data> txes;
870};
871template <class Archive>
872inline void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization::version_type ver)
873{
874 a & x.txes;
875 a & x.transfers;
876}
877#define UNSIGNED_TX_PREFIX "Electroneum unsigned tx set\003"
878TEST(Serialization, portability_unsigned_tx)
879{
880 const boost::filesystem::path filename = unit_test::data_dir / "unsigned_electroneum_tx";
881 std::string s;
883 bool r = epee::file_io_utils::load_file_to_string(filename.string(), s);
884 ASSERT_TRUE(r);
885 const size_t magiclen = strlen(UNSIGNED_TX_PREFIX);
886 ASSERT_FALSE(strncmp(s.c_str(), UNSIGNED_TX_PREFIX, magiclen));
887 unsigned_tx_set exported_txs;
888 s = s.substr(magiclen);
889 r = false;
890 try
891 {
892 std::istringstream iss(s);
894 ar >> exported_txs;
895 r = true;
896 }
897 catch (...)
898 {}
899 ASSERT_TRUE(r);
900 /*
901 fields of tools::wallet2::unsigned_tx_set to be checked:
902 std::vector<tx_construction_data> txes
903 std::vector<wallet2::transfer_details> m_transfers
904
905 fields of toolw::wallet2::tx_construction_data to be checked:
906 std::vector<cryptonote::tx_source_entry> sources
907 cryptonote::tx_destination_entry change_dts
908 std::vector<cryptonote::tx_destination_entry> splitted_dsts
909 std::list<size_t> selected_transfers
910 std::vector<uint8_t> extra
911 uint64_t unlock_time
912 bool use_rct
913 std::vector<cryptonote::tx_destination_entry> dests
914
915 fields of cryptonote::tx_source_entry to be checked:
916 std::vector<std::pair<uint64_t, rct::ctkey>> outputs
917 size_t real_output
918 crypto::public_key real_out_tx_key
919 size_t real_output_in_tx_index
920 uint64_t amount
921 bool rct
922 rct::key mask
923
924 fields of cryptonote::tx_destination_entry to be checked:
925 uint64_t amount
926 account_public_address addr
927 */
928 // txes
929 ASSERT_TRUE(exported_txs.txes.size() == 1);
930 auto& tcd = exported_txs.txes[0];
931 // tcd.sources
932 ASSERT_TRUE(tcd.sources.size() == 1);
933 auto& tse = tcd.sources[0];
934 // tcd.sources[0].outputs
935 ASSERT_TRUE(tse.outputs.size() == 5);
936 auto& out0 = tse.outputs[0];
937 auto& out1 = tse.outputs[1];
938 auto& out2 = tse.outputs[2];
939 auto& out3 = tse.outputs[3];
940 auto& out4 = tse.outputs[4];
941 ASSERT_TRUE(out0.first == 6295);
942 ASSERT_TRUE(out1.first == 14302);
943 ASSERT_TRUE(out2.first == 17598);
944 ASSERT_TRUE(out3.first == 18671);
945 ASSERT_TRUE(out4.first == 19760);
946 ASSERT_TRUE(epee::string_tools::pod_to_hex(out0.second) == "e7272cb589954ddeedd20de9411ed57265f154d41f33cec9ff69e5d642e09814096490b0ac85308342acf436cc0270d53abef9dc04c6202f2459e879bfd40ce6");
947 ASSERT_TRUE(epee::string_tools::pod_to_hex(out1.second) == "c3a9f49d1fe75939cc3feb39871ce0a7366c2879a63faa1a5cf34e65723b120a272ff0c7d84ab8b6ee3528d196450b0e28b3fed276bc2597a2b5b17afb9354ab");
948 ASSERT_TRUE(epee::string_tools::pod_to_hex(out2.second) == "176e239c8c39000c2275e2f63ed7d55c55e0843524091522bbd3d3b869044969021fad70fc1244115449d4754829ae7c47346342ee5d52a2cdd47dfc351d0ab0");
949 ASSERT_TRUE(epee::string_tools::pod_to_hex(out3.second) == "ef12d7946302fb064f2ba9df1a73d72233ac74664ed3b370580fa3bdc377542ad93f64898bd95851d6efe0d7bf2dbbea9b7c6b3c57e2c807e7b17d55b4622259");
950 ASSERT_TRUE(epee::string_tools::pod_to_hex(out4.second) == "0d8467e16e73d16510452b78823e082e05ee3a63788d40de577cf31eb555f0c8525096cbc88d00a841eed66f3cdb6f0a018e6ce9fb9433ed61afba15cbbebd04");
951 // tcd.sources[0].{real_output, real_out_tx_key, real_output_in_tx_index, amount, rct, mask}
952 ASSERT_TRUE(tse.real_output == 4);
953 ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.real_out_tx_key) == "4d86c7ba1c285fe4bc1cd7b54ba894fa89fa02fc6b0bbeea67d53251acd14a05");
954 ASSERT_TRUE(tse.real_output_in_tx_index == 1);
955 ASSERT_TRUE(tse.amount == 11066009260865);
956 ASSERT_TRUE(tse.rct);
957 ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703");
958 // tcd.change_dts
959 ASSERT_TRUE(tcd.change_dts.amount == 9631208773403);
960 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, tcd.change_dts.addr) == "etnjxQKSvwhVxnJ4VatxuJebGw3bk6EKLYVmksCHY7BTRiNiZFKWbhwVgHHBqwGwfuAqhjDJpNzDX1jkuKmBxSXU6bAiwJfVue");
961 // tcd.splitted_dsts
962 ASSERT_TRUE(tcd.splitted_dsts.size() == 2);
963 auto& splitted_dst0 = tcd.splitted_dsts[0];
964 auto& splitted_dst1 = tcd.splitted_dsts[1];
965 ASSERT_TRUE(splitted_dst0.amount == 1400000000000);
966 ASSERT_TRUE(splitted_dst1.amount == 9631208773403);
967 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst0.addr) == "etnkCu7s6mRGi3RJm5CKgZSFsJhbrhb2XRqPSdBqMiNnf2A7Nw3kncTLhZ3SbVJ2bH1W7pPq9LExDHVbHu9fTZJv1HeRSuyVUc");
968 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst1.addr) == "etnjxQKSvwhVxnJ4VatxuJebGw3bk6EKLYVmksCHY7BTRiNiZFKWbhwVgHHBqwGwfuAqhjDJpNzDX1jkuKmBxSXU6bAiwJfVue");
969 // tcd.selected_transfers
970 ASSERT_TRUE(tcd.selected_transfers.size() == 1);
971 ASSERT_TRUE(tcd.selected_transfers.front() == 2);
972 // tcd.extra
973 ASSERT_TRUE(tcd.extra.size() == 68);
974 // tcd.{unlock_time, use_rct}
975 ASSERT_TRUE(tcd.unlock_time == 0);
976 ASSERT_TRUE(tcd.use_rct);
977 // tcd.dests
978 ASSERT_TRUE(tcd.dests.size() == 1);
979 auto& dest = tcd.dests[0];
980 ASSERT_TRUE(dest.amount == 1400000000000);
981 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, dest.addr) == "etnkCu7s6mRGi3RJm5CKgZSFsJhbrhb2XRqPSdBqMiNnf2A7Nw3kncTLhZ3SbVJ2bH1W7pPq9LExDHVbHu9fTZJv1HeRSuyVUc");
982 // transfers
983 ASSERT_TRUE(exported_txs.transfers.size() == 3);
984 auto& td0 = exported_txs.transfers[0];
985 auto& td1 = exported_txs.transfers[1];
986 auto& td2 = exported_txs.transfers[2];
987 ASSERT_TRUE(td0.m_block_height == 818424);
988 ASSERT_TRUE(td1.m_block_height == 818522);
989 ASSERT_TRUE(td2.m_block_height == 818522);
990 ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_txid) =="15024343b38e77a1a9860dfed29921fa17e833fec837191a6b04fa7cb9605b8e");
991 ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_txid) == "ec34c9bb12b99af33d49691384eee5bed9171498ff04e59516505f35d1fc5efc");
992 ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_txid) == "6e7013684d35820f66c6679197ded9329bfe0e495effa47e7b25258799858dba");
993 ASSERT_TRUE(td0.m_internal_output_index == 0);
994 ASSERT_TRUE(td1.m_internal_output_index == 0);
995 ASSERT_TRUE(td2.m_internal_output_index == 1);
996 ASSERT_TRUE(td0.m_global_output_index == 19642);
997 ASSERT_TRUE(td1.m_global_output_index == 19757);
998 ASSERT_TRUE(td2.m_global_output_index == 19760);
999 ASSERT_TRUE (td0.m_spent);
1000 ASSERT_FALSE(td1.m_spent);
1001 ASSERT_FALSE(td2.m_spent);
1002 ASSERT_TRUE(td0.m_spent_height == 0);
1003 ASSERT_TRUE(td1.m_spent_height == 0);
1004 ASSERT_TRUE(td2.m_spent_height == 0);
1005 ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_key_image) == "c5680d3735b90871ca5e3d90cd82d6483eed1151b9ab75c2c8c3a7d89e00a5a8");
1006 ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_key_image) == "d54cbd435a8d636ad9b01b8d4f3eb13bd0cf1ce98eddf53ab1617f9b763e66c0");
1007 ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_key_image) == "6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76");
1008 ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_mask) == "0100000000000000000000000000000000000000000000000000000000000000");
1009 ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_mask) == "d3997a7b27fa199a377643b88cbd3f20f447496746dabe92d288730ecaeda007");
1010 ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703");
1011 ASSERT_TRUE(td0.m_amount == 13400845012231);
1012 ASSERT_TRUE(td1.m_amount == 1200000000000);
1013 ASSERT_TRUE(td2.m_amount == 11066009260865);
1014 ASSERT_TRUE(td0.m_rct);
1015 ASSERT_TRUE(td1.m_rct);
1016 ASSERT_TRUE(td2.m_rct);
1017 ASSERT_TRUE(td0.m_key_image_known);
1018 ASSERT_TRUE(td1.m_key_image_known);
1019 ASSERT_TRUE(td2.m_key_image_known);
1020 ASSERT_TRUE(td0.m_pk_index == 0);
1021 ASSERT_TRUE(td1.m_pk_index == 0);
1022 ASSERT_TRUE(td2.m_pk_index == 0);
1023}
1024
1025// ToDo : Change this test to test features relevant to the Electroneum Project (Wallet needs creating and such)
1026#define SIGNED_TX_PREFIX "Electroneum signed tx set\003"
1027TEST(Serialization, portability_signed_tx)
1028{
1029 const boost::filesystem::path filename = unit_test::data_dir / "signed_electroneum_tx";
1031 std::string s;
1032 bool r = epee::file_io_utils::load_file_to_string(filename.string(), s);
1033 ASSERT_TRUE(r);
1034 const size_t magiclen = strlen(SIGNED_TX_PREFIX);
1035 ASSERT_FALSE(strncmp(s.c_str(), SIGNED_TX_PREFIX, magiclen));
1036 tools::wallet2::signed_tx_set exported_txs;
1037 s = s.substr(magiclen);
1038 r = false;
1039 try
1040 {
1041 std::istringstream iss(s);
1043 ar >> exported_txs;
1044 r = true;
1045 }
1046 catch (...)
1047 {}
1048 ASSERT_TRUE(r);
1049 /*
1050 fields of tools::wallet2::signed_tx_set to be checked:
1051 std::vector<pending_tx> ptx
1052 std::vector<crypto::key_image> key_images
1053
1054 fields of tools::walllet2::pending_tx to be checked:
1055 cryptonote::transaction tx // TODO
1056 uint64_t dust
1057 uint64_t fee
1058 bool dust_added_to_fee
1059 cryptonote::tx_destination_entry change_dts
1060 std::list<size_t> selected_transfers
1061 std::string key_images
1062 crypto::secret_key tx_key
1063 std::vector<cryptonote::tx_destination_entry> dests
1064 tx_construction_data construction_data
1065 */
1066 // ptx
1067 ASSERT_TRUE(exported_txs.ptx.size() == 1);
1068 auto& ptx = exported_txs.ptx[0];
1069 // ptx.{dust, fee, dust_added_to_fee}
1070 ASSERT_TRUE (ptx.dust == 0);
1071 ASSERT_TRUE (ptx.fee == 34800487462);
1072 ASSERT_FALSE(ptx.dust_added_to_fee);
1073 // ptx.change.{amount, addr}
1074 ASSERT_TRUE(ptx.change_dts.amount == 9631208773403);
1075 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, ptx.change_dts.addr) == "etnjxQKSvwhVxnJ4VatxuJebGw3bk6EKLYVmksCHY7BTRiNiZFKWbhwVgHHBqwGwfuAqhjDJpNzDX1jkuKmBxSXU6bAiwJfVue");
1076 // ptx.selected_transfers
1077 ASSERT_TRUE(ptx.selected_transfers.size() == 1);
1078 ASSERT_TRUE(ptx.selected_transfers.front() == 2);
1079 // ptx.{key_images, tx_key}
1080 ASSERT_TRUE(ptx.key_images == "<6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76> ");
1081 ASSERT_TRUE(epee::string_tools::pod_to_hex(ptx.tx_key) == "0100000000000000000000000000000000000000000000000000000000000000");
1082 // ptx.dests
1083 ASSERT_TRUE(ptx.dests.size() == 1);
1084 ASSERT_TRUE(ptx.dests[0].amount == 1400000000000);
1085 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, ptx.dests[0].addr) == "etnkCu7s6mRGi3RJm5CKgZSFsJhbrhb2XRqPSdBqMiNnf2A7Nw3kncTLhZ3SbVJ2bH1W7pPq9LExDHVbHu9fTZJv1HeRSuyVUc");
1086 // ptx.construction_data
1087 auto& tcd = ptx.construction_data;
1088 ASSERT_TRUE(tcd.sources.size() == 1);
1089 auto& tse = tcd.sources[0];
1090 // ptx.construction_data.sources[0].outputs
1091 ASSERT_TRUE(tse.outputs.size() == 5);
1092 auto& out0 = tse.outputs[0];
1093 auto& out1 = tse.outputs[1];
1094 auto& out2 = tse.outputs[2];
1095 auto& out3 = tse.outputs[3];
1096 auto& out4 = tse.outputs[4];
1097 ASSERT_TRUE(out0.first == 6295);
1098 ASSERT_TRUE(out1.first == 14302);
1099 ASSERT_TRUE(out2.first == 17598);
1100 ASSERT_TRUE(out3.first == 18671);
1101 ASSERT_TRUE(out4.first == 19760);
1102 ASSERT_TRUE(epee::string_tools::pod_to_hex(out0.second) == "e7272cb589954ddeedd20de9411ed57265f154d41f33cec9ff69e5d642e09814096490b0ac85308342acf436cc0270d53abef9dc04c6202f2459e879bfd40ce6");
1103 ASSERT_TRUE(epee::string_tools::pod_to_hex(out1.second) == "c3a9f49d1fe75939cc3feb39871ce0a7366c2879a63faa1a5cf34e65723b120a272ff0c7d84ab8b6ee3528d196450b0e28b3fed276bc2597a2b5b17afb9354ab");
1104 ASSERT_TRUE(epee::string_tools::pod_to_hex(out2.second) == "176e239c8c39000c2275e2f63ed7d55c55e0843524091522bbd3d3b869044969021fad70fc1244115449d4754829ae7c47346342ee5d52a2cdd47dfc351d0ab0");
1105 ASSERT_TRUE(epee::string_tools::pod_to_hex(out3.second) == "ef12d7946302fb064f2ba9df1a73d72233ac74664ed3b370580fa3bdc377542ad93f64898bd95851d6efe0d7bf2dbbea9b7c6b3c57e2c807e7b17d55b4622259");
1106 ASSERT_TRUE(epee::string_tools::pod_to_hex(out4.second) == "0d8467e16e73d16510452b78823e082e05ee3a63788d40de577cf31eb555f0c8525096cbc88d00a841eed66f3cdb6f0a018e6ce9fb9433ed61afba15cbbebd04");
1107 // ptx.construction_data.sources[0].{real_output, real_out_tx_key, real_output_in_tx_index, amount, rct, mask}
1108 ASSERT_TRUE(tse.real_output == 4);
1109 ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.real_out_tx_key) == "4d86c7ba1c285fe4bc1cd7b54ba894fa89fa02fc6b0bbeea67d53251acd14a05");
1110 ASSERT_TRUE(tse.real_output_in_tx_index == 1);
1111 ASSERT_TRUE(tse.amount == 11066009260865);
1112 ASSERT_TRUE(tse.rct);
1113 ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703");
1114 // ptx.construction_data.change_dts
1115 ASSERT_TRUE(tcd.change_dts.amount == 9631208773403);
1116 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, tcd.change_dts.addr) == "etnjxQKSvwhVxnJ4VatxuJebGw3bk6EKLYVmksCHY7BTRiNiZFKWbhwVgHHBqwGwfuAqhjDJpNzDX1jkuKmBxSXU6bAiwJfVue");
1117 // ptx.construction_data.splitted_dsts
1118 ASSERT_TRUE(tcd.splitted_dsts.size() == 2);
1119 auto& splitted_dst0 = tcd.splitted_dsts[0];
1120 auto& splitted_dst1 = tcd.splitted_dsts[1];
1121 ASSERT_TRUE(splitted_dst0.amount == 1400000000000);
1122 ASSERT_TRUE(splitted_dst1.amount == 9631208773403);
1123 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst0.addr) == "etnkCu7s6mRGi3RJm5CKgZSFsJhbrhb2XRqPSdBqMiNnf2A7Nw3kncTLhZ3SbVJ2bH1W7pPq9LExDHVbHu9fTZJv1HeRSuyVUc");
1124 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst1.addr) == "etnjxQKSvwhVxnJ4VatxuJebGw3bk6EKLYVmksCHY7BTRiNiZFKWbhwVgHHBqwGwfuAqhjDJpNzDX1jkuKmBxSXU6bAiwJfVue");
1125 // ptx.construction_data.selected_transfers
1126 ASSERT_TRUE(tcd.selected_transfers.size() == 1);
1127 ASSERT_TRUE(tcd.selected_transfers.front() == 2);
1128 // ptx.construction_data.extra
1129 ASSERT_TRUE(tcd.extra.size() == 68);
1130 // ptx.construction_data.{unlock_time, use_rct}
1131 ASSERT_TRUE(tcd.unlock_time == 0);
1132 ASSERT_TRUE(tcd.use_rct);
1133 // ptx.construction_data.dests
1134 ASSERT_TRUE(tcd.dests.size() == 1);
1135 auto& dest = tcd.dests[0];
1136 ASSERT_TRUE(dest.amount == 1400000000000);
1137 ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, dest.addr) == "etnkCu7s6mRGi3RJm5CKgZSFsJhbrhb2XRqPSdBqMiNnf2A7Nw3kncTLhZ3SbVJ2bH1W7pPq9LExDHVbHu9fTZJv1HeRSuyVUc");
1138 // key_images
1139 ASSERT_TRUE(exported_txs.key_images.size() == 3);
1140 auto& ki0 = exported_txs.key_images[0];
1141 auto& ki1 = exported_txs.key_images[1];
1142 auto& ki2 = exported_txs.key_images[2];
1143 ASSERT_TRUE(epee::string_tools::pod_to_hex(ki0) == "c5680d3735b90871ca5e3d90cd82d6483eed1151b9ab75c2c8c3a7d89e00a5a8");
1144 ASSERT_TRUE(epee::string_tools::pod_to_hex(ki1) == "d54cbd435a8d636ad9b01b8d4f3eb13bd0cf1ce98eddf53ab1617f9b763e66c0");
1145 ASSERT_TRUE(epee::string_tools::pod_to_hex(ki2) == "6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76");
1146}
1147
1148TEST(Serialization, difficulty_type)
1149{
1150 std::vector<cryptonote::difficulty_type> v_original;
1151
1152 for(int i = 0; i != 100; i++)
1153 {
1154 v_original.push_back(cryptonote::difficulty_type("117868131154734361989189100"));
1155 if(v_original.size() > 1)
1156 v_original.back() *= v_original[v_original.size()-2];
1157 }
1158
1159 std::stringstream ss;
1161 a << v_original;
1162
1163 std::vector<cryptonote::difficulty_type> v_unserialized;
1164
1166 a2 >> v_unserialized;
1167
1168 ASSERT_EQ(v_original, v_unserialized);
1169}
std::vector< std::vector< crypto::signature > > signatures
size_t size() const
Definition wallet2.h:181
void load(const std::string &wallet, const epee::wipeable_string &password)
Definition wallet2.cpp:5833
std::vector< transfer_details > transfer_container
Definition wallet2.h:449
#define ASSERT_EQ(val1, val2)
Definition gtest.h:1956
#define ASSERT_FALSE(condition)
Definition gtest.h:1868
#define TEST(test_case_name, test_name)
Definition gtest.h:2187
#define ASSERT_TRUE(condition)
Definition gtest.h:1865
const char * res
const char * key
JSON archive.
crypto namespace.
Definition crypto.cpp:58
signed int int32_t
Definition hash.h:124
POD_CLASS signature
Definition crypto.h:108
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
void cn_fast_hash(const void *data, size_t length, char *hash)
unsigned __int64 uint64_t
Definition hash.h:137
POD_CLASS public_key
Definition crypto.h:79
POD_CLASS key_image
Definition crypto.h:105
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition crypto.h:295
unsigned int uint32_t
Definition hash.h:127
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition crypto.h:262
POD_CLASS hash
Definition hash.h:50
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
boost::multiprecision::uint128_t difficulty_type
Definition difficulty.h:43
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
std::string pod_to_hex(const t_pod_type &s)
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
device & get_device(const std::string &device_descriptor)
Definition device.cpp:95
void hash_to_scalar(key &hash, const void *data, const std::size_t l)
Definition rctOps.cpp:536
void skpkGen(key &sk, key &pk)
Definition rctOps.cpp:284
std::vector< key > keyV
Definition rctTypes.h:88
std::vector< keyV > keyM
Definition rctTypes.h:89
std::vector< ctkeyV > ctkeyM
Definition rctTypes.h:101
key skGen()
Definition rctOps.cpp:258
tuple< key, key > skpkGen()
Definition rctOps.cpp:290
std::vector< ctkey > ctkeyV
Definition rctTypes.h:100
keyV skvGen(size_t rows)
Definition rctOps.cpp:266
key zero()
Definition rctOps.h:70
tuple< ctkey, ctkey > ctskpkGen(etn_amount amount)
Definition rctOps.cpp:302
@ RangeProofPaddedBulletproof
Definition rctTypes.h:235
rctSig genRctSimple(const key &message, const ctkeyV &inSk, const keyV &destinations, const vector< etn_amount > &inamounts, const vector< etn_amount > &outamounts, etn_amount txnFee, const ctkeyM &mixRing, const keyV &amount_keys, const std::vector< multisig_kLRki > *kLRki, multisig_out *msout, const std::vector< unsigned int > &index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev)
Definition rctSigs.cpp:752
void skGen(key &sk)
Definition rctOps.cpp:253
keyM keyMInit(size_t rows, size_t cols)
Definition rctOps.cpp:227
bool parse_binary(const std::string &blob, T &v)
bool dump_binary(T &v, std::string &blob)
STL namespace.
boost::filesystem::path data_dir
Definition main.cpp:50
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
#define UNSIGNED_TX_PREFIX
bool try_parse(const string &blob)
#define SIGNED_TX_PREFIX
#define OUTPUT_EXPORT_FILE_MAGIC
void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization::version_type ver)
#define BEGIN_SERIALIZE_OBJECT()
#define BLOB_SERIALIZER(T)
#define FIELD(f)
#define END_SERIALIZE()
#define VARIANT_TAG(Archive, Type, Tag)
CXA_THROW_INFO_T void(* dest)(void *))
unsigned __int64 uint64_t
Definition stdint.h:136
bool operator==(const Blob &rhs) const
uint32_t b
uint64_t a
vector< int16_t > vi
vector< boost::variant< Struct, int32_t > > si
int32_t a
char blob[8]
int32_t b
... wouldn't a class be better?
Definition hash.h:93
crypto::key_image k_image
std::vector< uint64_t > key_offsets
a archive using the JSON standard
rct::keyV V
Definition rctTypes.h:181
rctSigPrunable p
Definition rctTypes.h:437
std::vector< mgSig > MGs
Definition rctTypes.h:321
std::vector< Bulletproof > bulletproofs
Definition rctTypes.h:320
static bool serialize(Archive &ar, Struct &s)
std::vector< crypto::key_image > key_images
Definition wallet2.h:506
std::vector< pending_tx > ptx
Definition wallet2.h:505
tools::wallet2::transfer_container transfers
std::vector< tools::wallet2::tx_construction_data > txes
#define ASSERT_EQ_MAP(val, map, key)
for dealing with variants