forked from UkoeHB/monero
-
Notifications
You must be signed in to change notification settings - Fork 2
/
sp_wallet_show_enotes.cpp
592 lines (505 loc) · 24.9 KB
/
sp_wallet_show_enotes.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
// Copyright (c) 2023, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/format.hpp>
#include <boost/format/format_fwd.hpp>
#include <boost/none.hpp>
#include <cstddef>
#include <cstdint>
#include <ostream>
#include <utility>
#include <vector>
#include "boost/multiprecision/cpp_int.hpp"
#include "common/container_helpers.h"
#include "common/scoped_message_writer.h"
#include "crypto/crypto.h"
#include "crypto/x25519.h"
#include "cryptonote_basic/subaddress_index.h"
#include "encrypt_file.h"
#include "enote_store.h"
#include "gtest/gtest.h"
#include "jamtis_mock_keys.h"
#include "legacy_enote_types.h"
#include "legacy_mock_keys.h"
#include "misc_language.h"
#include "misc_log_ex.h"
#include "mock_ledger_context.h"
#include "ringct/rctOps.h"
#include "ringct/rctTypes.h"
#include "seraphis_core/binned_reference_set.h"
#include "seraphis_core/binned_reference_set_utils.h"
#include "seraphis_core/discretized_fee.h"
#include "seraphis_core/jamtis_address_tag_utils.h"
#include "seraphis_core/jamtis_address_utils.h"
#include "seraphis_core/jamtis_core_utils.h"
#include "seraphis_core/jamtis_destination.h"
#include "seraphis_core/jamtis_enote_utils.h"
#include "seraphis_core/jamtis_payment_proposal.h"
#include "seraphis_core/jamtis_support_types.h"
#include "seraphis_core/legacy_core_utils.h"
#include "seraphis_core/legacy_enote_utils.h"
#include "seraphis_core/sp_core_enote_utils.h"
#include "seraphis_core/sp_core_types.h"
#include "seraphis_core/tx_extra.h"
#include "seraphis_crypto/sp_composition_proof.h"
#include "seraphis_crypto/sp_crypto_utils.h"
#include "seraphis_impl/enote_store_utils.h"
// #include "seraphis_impl/scanning_context_simple.h"
#include "seraphis_impl/tx_fee_calculator_squashed_v1.h"
#include "seraphis_impl/tx_input_selection_output_context_v1.h"
#include "seraphis_main/contextual_enote_record_types.h"
#include "seraphis_main/contextual_enote_record_utils.h"
#include "seraphis_main/enote_record_types.h"
#include "seraphis_main/enote_record_utils.h"
#include "seraphis_main/scan_machine_types.h"
#include "seraphis_main/sp_knowledge_proof_types.h"
#include "seraphis_main/sp_knowledge_proof_utils.h"
#include "seraphis_main/tx_builder_types.h"
#include "seraphis_main/tx_builders_inputs.h"
#include "seraphis_main/tx_builders_legacy_inputs.h"
#include "seraphis_main/tx_builders_mixed.h"
#include "seraphis_main/tx_builders_outputs.h"
#include "seraphis_main/tx_component_types.h"
#include "seraphis_main/tx_input_selection.h"
#include "seraphis_main/txtype_squashed_v1.h"
#include "seraphis_mocks/seraphis_mocks.h"
#include "seraphis_wallet/show_enotes.h"
#include "seraphis_wallet/transaction_history.h"
#include "seraphis_wallet/transaction_utils.h"
#include "serialization_demo_utils.h"
#include "serialization_types.h"
using namespace sp;
using namespace jamtis;
using namespace sp::mocks;
using namespace jamtis::mocks;
using namespace sp::knowledge_proofs;
static void fill_tx_store(const SpTxSquashedV1 &single_tx,
const std::vector<JamtisPaymentProposalSelfSendV1> &selfsend_payments,
const std::vector<JamtisPaymentProposalV1> &normal_payments,
SpTxStatus status,
SpEnoteStore &enote_store_in_out,
SpTransactionHistory &tx_history_in_out)
{
/// 1. prepare variables of tx_store
rct::key tx_id;
std::vector<std::pair<JamtisDestinationV1, rct::xmr_amount>> outlays_vec;
std::vector<crypto::key_image> legacy_spent_ki;
std::vector<crypto::key_image> sp_spent_ki;
TransactionRecordV1 record;
SpContextualEnoteRecordV1 temp_sp_enote_record{};
LegacyContextualEnoteRecordV1 temp_legacy_enote_record{};
// a. tx_id
get_sp_tx_squashed_v1_txid(single_tx, tx_id);
// b. legacy_spent_key_images
legacy_spent_ki.clear();
for (auto legacy_images : single_tx.legacy_input_images)
{
legacy_spent_ki.push_back(legacy_images.key_image);
}
// c. sp_spent_key_images
sp_spent_ki.clear();
for (auto sp_images : single_tx.sp_input_images)
{
sp_spent_ki.push_back(sp_images.core.key_image);
}
// d. total amount sent
rct::xmr_amount total_amount_sent{};
for (auto outs : normal_payments)
{
total_amount_sent += outs.amount;
}
// e. fee
rct::xmr_amount tx_fee;
try_get_fee_value(single_tx.tx_fee, tx_fee);
// f. get TransactionRecord
record = TransactionRecordV1{
legacy_spent_ki, sp_spent_ki, selfsend_payments, normal_payments, total_amount_sent, tx_fee};
// 2. add record to tx_record by tx_id
tx_history_in_out.add_entry_to_tx_records(tx_id, std::move(record));
// 3. get ContextualEnote record
ContextualRecordVariant temp_contextual_record;
if (sp_spent_ki.size() > 0)
{
enote_store_in_out.try_get_sp_enote_record(sp_spent_ki[0], temp_sp_enote_record);
temp_contextual_record = temp_sp_enote_record;
}
else
{
enote_store_in_out.try_get_legacy_enote_record(legacy_spent_ki[0], temp_legacy_enote_record);
temp_contextual_record = temp_legacy_enote_record;
}
// 4. update with either the info from legacy or sp context
tx_history_in_out.add_entry_txs(status, spent_context_ref(temp_contextual_record).block_index, tx_id);
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
static void add_coinbase_enotes(MockLedgerContext &ledger_context,
SpEnoteStore &enote_store_in_out,
SpTransactionHistory &tx_history_in_out,
const legacy_mock_keys &legacy_user_keys_A,
const jamtis_mock_keys &user_keys_A,
const uint64_t number_txs)
{
/// config
const std::size_t legacy_ring_size{2};
const scanning::ScanMachineConfig refresh_config{
.reorg_avoidance_increment = 1, .max_chunk_size_hint = 1, .max_partialscan_attempts = 0};
const FeeCalculatorMockTrivial fee_calculator; // trivial calculator for easy fee (fee = fee/weight * 1 weight)
const SpBinnedReferenceSetConfigV1 bin_config{.bin_radius = 1, .num_bin_members = 2};
/// prepare for membership proofs
// a. add enough fake enotes to the ledger so we can reliably make seraphis membership proofs
std::vector<rct::xmr_amount> fake_sp_enote_amounts(
static_cast<std::size_t>(compute_bin_width(bin_config.bin_radius)), 0);
JamtisDestinationV1 fake_destination;
fake_destination = gen_jamtis_destination_v1();
send_sp_coinbase_amounts_to_user(fake_sp_enote_amounts, fake_destination, ledger_context);
// b. add enough fake legacy enotes to the ledger so we can reliably make legacy ring signatures
std::vector<rct::xmr_amount> fake_legacy_enote_amounts(static_cast<std::size_t>(legacy_ring_size), 0);
const rct::key fake_legacy_spendkey{rct::pkGen()};
const rct::key fake_legacy_viewkey{rct::pkGen()};
send_legacy_coinbase_amounts_to_user(
fake_legacy_enote_amounts, fake_legacy_spendkey, fake_legacy_viewkey, ledger_context);
/// make two users
// b. legacy user address
rct::key legacy_subaddr_spendkey_A;
rct::key legacy_subaddr_viewkey_A;
cryptonote::subaddress_index legacy_subaddr_index_A;
std::unordered_map<rct::key, cryptonote::subaddress_index> legacy_subaddress_map_A;
gen_legacy_subaddress(legacy_user_keys_A.Ks,
legacy_user_keys_A.k_v,
legacy_subaddr_spendkey_A,
legacy_subaddr_viewkey_A,
legacy_subaddr_index_A);
legacy_subaddress_map_A[legacy_subaddr_spendkey_A] = legacy_subaddr_index_A;
// user keys B
jamtis_mock_keys user_keys_B;
make_jamtis_mock_keys(user_keys_B);
// b. destination address
JamtisDestinationV1 destination_A;
JamtisDestinationV1 destination_B;
make_random_address_for_user(user_keys_A, destination_A);
make_random_address_for_user(user_keys_B, destination_B);
// c. user enote stores (refresh index = 0; seraphis initial block = 0; default spendable age = 0)
SpEnoteStore enote_store_B{0, 0, 0};
// d. user input selectors
const InputSelectorMockV1 input_selector_A{enote_store_in_out};
const InputSelectorMockV1 input_selector_B{enote_store_B};
/// initial funding for user A: seraphis 1000
/// initial funding for user A: legacy 1000
// send_legacy_coinbase_amounts_to_user(
// {1000, 1000, 1000, 1000, 1000}, legacy_subaddr_spendkey_A, legacy_subaddr_viewkey_A, ledger_context);
for (uint64_t i = 0; i < number_txs; i++)
{
send_legacy_coinbase_amounts_to_user(
{100}, legacy_subaddr_spendkey_A, legacy_subaddr_viewkey_A, ledger_context);
refresh_user_enote_store_legacy_full(legacy_user_keys_A.Ks,
legacy_subaddress_map_A,
legacy_user_keys_A.k_s,
legacy_user_keys_A.k_v,
refresh_config,
ledger_context,
enote_store_in_out);
// send_sp_coinbase_amounts_to_user({1000, 1000, 1000, 1000, 1000}, destination_A, ledger_context);
refresh_user_enote_store(user_keys_A, refresh_config, ledger_context, enote_store_in_out);
}
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
static void make_transfers2(MockLedgerContext &ledger_context,
SpEnoteStore &enote_store_in_out,
SpTransactionHistory &tx_history_in_out,
const legacy_mock_keys &legacy_user_keys_A,
const jamtis_mock_keys &user_keys_A,
const uint64_t number_txs)
{
/// config
const std::size_t max_inputs{1000};
const std::size_t fee_per_tx_weight{1};
const std::size_t legacy_ring_size{2};
const std::size_t ref_set_decomp_n{2};
const std::size_t ref_set_decomp_m{2};
const scanning::ScanMachineConfig refresh_config{
.reorg_avoidance_increment = 1, .max_chunk_size_hint = 1, .max_partialscan_attempts = 0};
const FeeCalculatorMockTrivial fee_calculator; // trivial calculator for easy fee (fee = fee/weight * 1 weight)
const SpBinnedReferenceSetConfigV1 bin_config{.bin_radius = 1, .num_bin_members = 2};
/// prepare for membership proofs
// a. add enough fake enotes to the ledger so we can reliably make seraphis membership proofs
std::vector<rct::xmr_amount> fake_sp_enote_amounts(
static_cast<std::size_t>(compute_bin_width(bin_config.bin_radius)), 0);
JamtisDestinationV1 fake_destination;
fake_destination = gen_jamtis_destination_v1();
send_sp_coinbase_amounts_to_user(fake_sp_enote_amounts, fake_destination, ledger_context);
// b. add enough fake legacy enotes to the ledger so we can reliably make legacy ring signatures
std::vector<rct::xmr_amount> fake_legacy_enote_amounts(static_cast<std::size_t>(legacy_ring_size), 0);
const rct::key fake_legacy_spendkey{rct::pkGen()};
const rct::key fake_legacy_viewkey{rct::pkGen()};
send_legacy_coinbase_amounts_to_user(
fake_legacy_enote_amounts, fake_legacy_spendkey, fake_legacy_viewkey, ledger_context);
/// make two users
// b. legacy user address
rct::key legacy_subaddr_spendkey_A;
rct::key legacy_subaddr_viewkey_A;
cryptonote::subaddress_index legacy_subaddr_index_A;
std::unordered_map<rct::key, cryptonote::subaddress_index> legacy_subaddress_map_A;
gen_legacy_subaddress(legacy_user_keys_A.Ks,
legacy_user_keys_A.k_v,
legacy_subaddr_spendkey_A,
legacy_subaddr_viewkey_A,
legacy_subaddr_index_A);
legacy_subaddress_map_A[legacy_subaddr_spendkey_A] = legacy_subaddr_index_A;
// user keys B
jamtis_mock_keys user_keys_B;
make_jamtis_mock_keys(user_keys_B);
// b. destination address
JamtisDestinationV1 destination_A;
JamtisDestinationV1 destination_B;
make_random_address_for_user(user_keys_A, destination_A);
make_random_address_for_user(user_keys_B, destination_B);
// c. user enote stores (refresh index = 0; seraphis initial block = 0; default spendable age = 0)
SpEnoteStore enote_store_B{0, 0, 0};
// d. user input selectors
const InputSelectorMockV1 input_selector_A{enote_store_in_out};
const InputSelectorMockV1 input_selector_B{enote_store_B};
/// variables of one tx
SpTxSquashedV1 single_tx;
const TxValidationContextMock tx_validation_context{ledger_context};
std::vector<JamtisPaymentProposalV1> normal_payments;
std::vector<JamtisPaymentProposalSelfSendV1> selfsend_payments;
/// Send 5 confirmed txs
for (int i = 0; i < number_txs; i++)
{
rct::xmr_amount to_send{10};
// rct::xmr_amount to_send{static_cast<uint64_t>(rand() % 100)};
// std::cout << "to send: " << to_send << std::endl;
std::pair<JamtisDestinationV1, rct::xmr_amount> outlays{destination_B, to_send};
// 1. make one tx
construct_tx_for_mock_ledger_v1(legacy_user_keys_A,
user_keys_A,
input_selector_A,
fee_calculator,
fee_per_tx_weight,
max_inputs,
{{outlays.second, outlays.first, TxExtra{}}},
legacy_ring_size,
ref_set_decomp_n,
ref_set_decomp_m,
bin_config,
ledger_context,
single_tx,
selfsend_payments,
normal_payments);
// 2. validate and submit to the mock ledger
const TxValidationContextMock tx_validation_context{ledger_context};
CHECK_AND_ASSERT_THROW_MES(validate_tx(single_tx, tx_validation_context),
"transfer funds single mock unconfirmed sp only: validating tx failed.");
CHECK_AND_ASSERT_THROW_MES(try_add_tx_to_ledger(single_tx, ledger_context),
"transfer funds single mock unconfirmed sp only: validating tx failed.");
// 3. refresh user stores
refresh_user_enote_store(user_keys_A, refresh_config, ledger_context, enote_store_in_out);
refresh_user_enote_store_legacy_full(legacy_user_keys_A.Ks,
legacy_subaddress_map_A,
legacy_user_keys_A.k_s,
legacy_user_keys_A.k_v,
refresh_config,
ledger_context,
enote_store_in_out);
// 4. add tx to tx_records
fill_tx_store(single_tx,
selfsend_payments,
normal_payments,
SpTxStatus::CONFIRMED,
enote_store_in_out,
tx_history_in_out);
}
// // Send 5 unconfirmed_txs
// for (int i = 0; i < number_txs; i++)
// {
// std::pair<JamtisDestinationV1, rct::xmr_amount> outlays{destination_B, rand() % 100};
// // 1. make one tx
// construct_tx_for_mock_ledger_v1(legacy_user_keys_A,
// user_keys_A,
// input_selector_A,
// fee_calculator,
// fee_per_tx_weight,
// max_inputs,
// {{outlays.second, outlays.first, TxExtra{}}},
// legacy_ring_size,
// ref_set_decomp_n,
// ref_set_decomp_m,
// bin_config,
// ledger_context,
// single_tx,
// selfsend_payments,
// normal_payments);
// // 2. validate and submit to the mock ledger
// CHECK_AND_ASSERT_THROW_MES(validate_tx(single_tx, tx_validation_context),
// "transfer funds single mock unconfirmed sp only: validating tx failed.");
// CHECK_AND_ASSERT_THROW_MES(try_add_tx_to_ledger(single_tx, ledger_context),
// "transfer funds single mock unconfirmed sp only: validating tx failed.");
// // 3. refresh user stores
// refresh_user_enote_store(user_keys_A, refresh_config, ledger_context, enote_store_in_out);
// // 4. add tx to tx_records
// fill_tx_store(single_tx,
// selfsend_payments,
// normal_payments,
// SpTxStatus::UNCONFIRMED,
// enote_store_in_out,
// tx_history_in_out);
// }
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
TEST(seraphis_wallet_show, show_enotes_all)
{
// Test to display info stored in the tx_store class
// 1. generate enote_store and tx_history
SpEnoteStore enote_store_A{0, 0, 0};
SpTransactionHistory tx_history_A;
/// mock ledger context for this test
MockLedgerContext ledger_context{0, 10000};
// 2. generate user A keys
legacy_mock_keys legacy_user_keys_A;
jamtis_mock_keys user_keys_A;
make_jamtis_mock_keys(user_keys_A);
make_legacy_mock_keys(legacy_user_keys_A);
std::vector<ContextualRecordVariant> enote_records;
// 3. add coinbase enotes
add_coinbase_enotes(ledger_context, enote_store_A, tx_history_A, legacy_user_keys_A, user_keys_A, 10);
// 4. get all enotes initially
std::cout << "Initial account statement: " << std::endl;
get_enotes(enote_store_A, SpTxDirectionStatus::ALL, {0, -1}, enote_records);
show_enotes(enote_records);
// 5. make transfers to fill enote_store and tx_store
make_transfers2(ledger_context, enote_store_A, tx_history_A, legacy_user_keys_A, user_keys_A, 10);
std::cout << "Account statement after transaction: " << std::endl;
// 6. show and filter enotes after transactions
get_enotes(enote_store_A, SpTxDirectionStatus::ALL, {0, -1}, enote_records);
show_enotes(enote_records);
get_enotes(enote_store_A, SpTxDirectionStatus::ALL, {0, -1}, enote_records);
show_enotes(enote_records);
get_enotes(enote_store_A, SpTxDirectionStatus::IN_ONCHAIN, {0, -1}, enote_records);
show_enotes(enote_records);
get_enotes(enote_store_A, SpTxDirectionStatus::OUT_ONCHAIN, {0, -1}, enote_records);
show_enotes(enote_records);
get_enotes(enote_store_A, SpTxDirectionStatus::ALL, {20, 40}, enote_records);
show_enotes(enote_records);
std::cout << "Balance onchain : "
<< get_balance(enote_store_A, {SpEnoteOriginStatus::ONCHAIN}, {SpEnoteSpentStatus::SPENT_ONCHAIN})
<< std::endl;
}
//-------------------------------------------------------------------------------------------------------------------
TEST(seraphis_wallet_show, show_legacy_enote_with_sent_proof)
{
// 1. generate enote_store and tx_store
SpEnoteStore enote_store_A{0, 0, 0};
SpTransactionHistory tx_history_A;
/// mock ledger context for this test
MockLedgerContext ledger_context{0, 10000};
// 2. generate user A keys
legacy_mock_keys legacy_user_keys_A;
jamtis_mock_keys user_keys_A;
make_jamtis_mock_keys(user_keys_A);
make_legacy_mock_keys(legacy_user_keys_A);
// 3. add coinbase enotes
add_coinbase_enotes(ledger_context, enote_store_A, tx_history_A, legacy_user_keys_A, user_keys_A, 1);
// 4. get all enotes initially
std::cout << "1) Initial account statement: " << std::endl;
std::vector<ContextualRecordVariant> enote_records;
get_enotes(enote_store_A, SpTxDirectionStatus::ALL, {0, -1}, enote_records);
show_enotes(enote_records);
// 5. make transfers to fill enote_store and tx_store
make_transfers2(ledger_context, enote_store_A, tx_history_A, legacy_user_keys_A, user_keys_A, 1);
// 6. show and filter enotes after transactions
std::cout << "2) Account statement after transaction: " << std::endl;
get_enotes(enote_store_A, SpTxDirectionStatus::ALL, {0, -1}, enote_records);
show_enotes(enote_records);
// 7. get specific enote
const auto range_confirmed{tx_history_A.get_last_N_txs(SpTxStatus::CONFIRMED, 1)};
rct::key tx_id_proof = range_confirmed.begin()->second;
// 8. from tx_id get enote_record
TransactionRecordV1 tx_record;
tx_history_A.try_get_tx_record_from_txid(tx_id_proof, tx_record);
// 9. show specific enote
std::cout << "3) Show specific enote with key-image: " << tx_record.legacy_spent_enotes[0] << std::endl;
show_specific_enote(enote_store_A, tx_history_A, tx_record.legacy_spent_enotes[0]);
// 10. From tx_id get all output enotes of a tx by querying node.
std::vector<SpEnoteVariant> out_enotes = ledger_context.get_sp_enotes_out_from_tx(tx_id_proof);
// 11. get input context
rct::key input_context;
make_jamtis_input_context_standard(tx_record.legacy_spent_enotes, tx_record.sp_spent_enotes, input_context);
// 12. try to match enotes with destinations
std::vector<EnoteOutInfo> enote_out_info;
CHECK_AND_ASSERT_THROW_MES(get_enote_out_info(out_enotes,
tx_record.normal_payments,
tx_record.selfsend_payments,
input_context,
user_keys_A.k_vb,
enote_out_info),
"Error in get_enote_out_info. Could not match onetime adresses with destinations.");
// 13. make enote ownership proof for normal and selfsend enotes
std::cout << "4) Get sent_proof of enote using the info obtained looking where it was spent. " << std::endl;
std::string str_proof;
for (auto enote_info : enote_out_info)
{
if (!enote_info.selfsend)
{
std::cout << "Making proof for enote: " << onetime_address_ref(enote_info.enote)
<< " with amount: " << enote_info.amount << "XMR"
<< " and amount commitment: " << amount_commitment_ref(enote_info.enote) << std::endl;
str_proof = tx_history_A.get_enote_sent_proof(tx_id_proof,
onetime_address_ref(enote_info.enote),
enote_info.destination,
user_keys_A.k_vb,
enote_info.selfsend,
enote_info.amount,
enote_info.amount_blinding_factor,
amount_commitment_ref(enote_info.enote),
boost::none);
std::cout << "Proof generated: " << str_proof << std::endl;
std::cout << " ---------------------------------------------------- " << std::endl;
std::cout << "From the verifier side, he needs the proof, the onetime-address and the amount commitment."
<< std::endl;
// read enote ownership proof
CHECK_AND_ASSERT_THROW_MES(read_enote_sent_proof(boost::none,
str_proof,
amount_commitment_ref(enote_info.enote),
onetime_address_ref(enote_info.enote)),
"Verification of enote_sent_proof failed.");
// std::cout << "If the verifier refuses to accept the proof, the prover can openly publish: the "
// "ephemeral_private_key and the recipient address. So any third party looking at the proof "
// "must agree that the person in possession of those information created the transaction and "
// "the address claimed indeed received the funds."
// << std::endl;
// std::cout << "There is a big problem though, once all these info is revealed anyone can claim that they "
// "made this transaction. So if this point is reached then only the re-generation of the "
// "transaction with the input parameters can prove that the person made the transaction. So the "
// "prover should provide a legacy_spend_proof."
// << std::endl;
}
}
}
//-------------------------------------------------------------------------------------------------------------------