Electroneum
Loading...
Searching...
No Matches
chaingen.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 <vector>
33#include <iostream>
34#include <sstream>
35#include <algorithm>
36#include <array>
37#include <random>
38#include <sstream>
39#include <fstream>
40
41#include "include_base_utils.h"
42
43#include "console_handler.h"
44
45#include "p2p/net_node.h"
50
51#include "chaingen.h"
52#include "device/device.hpp"
53using namespace std;
54
55using namespace epee;
56using namespace crypto;
57using namespace cryptonote;
58
59
60void test_generator::get_block_chain(std::vector<block_info>& blockchain, const crypto::hash& head, size_t n) const
61{
62 crypto::hash curr = head;
63 while (null_hash != curr && blockchain.size() < n)
64 {
65 auto it = m_blocks_info.find(curr);
66 if (m_blocks_info.end() == it)
67 {
68 throw std::runtime_error("block hash wasn't found");
69 }
70
71 blockchain.push_back(it->second);
72 curr = it->second.prev_id;
73 }
74
75 std::reverse(blockchain.begin(), blockchain.end());
76}
77
78void test_generator::get_last_n_block_weights(std::vector<size_t>& block_weights, const crypto::hash& head, size_t n) const
79{
80 std::vector<block_info> blockchain;
81 get_block_chain(blockchain, head, n);
82 BOOST_FOREACH(auto& bi, blockchain)
83 {
84 block_weights.push_back(bi.block_weight);
85 }
86}
87
89{
90 auto it = m_blocks_info.find(blk_id);
91 if (it == m_blocks_info.end())
92 throw std::runtime_error("block hash wasn't found");
93
94 return it->second.already_generated_coins;
95}
96
98{
99 crypto::hash blk_hash;
100 get_block_hash(blk, blk_hash);
101 return get_already_generated_coins(blk_hash);
102}
103
104void test_generator::add_block(const cryptonote::block& blk, size_t txs_weight, std::vector<size_t>& block_weights, uint64_t already_generated_coins, uint8_t hf_version)
105{
106 const size_t block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
107 uint64_t block_reward;
108 get_block_reward(misc_utils::median(block_weights), block_weight, already_generated_coins, block_reward, hf_version, get_block_height(blk));
109 m_blocks_info[get_block_hash(blk)] = block_info(blk.prev_id, already_generated_coins + block_reward, block_weight);
110}
111
113 const cryptonote::account_base& miner_acc, uint64_t timestamp, uint64_t already_generated_coins,
114 std::vector<size_t>& block_weights, const std::list<cryptonote::transaction>& tx_list,
115 const boost::optional<uint8_t>& hf_ver)
116{
117 blk.major_version = hf_ver ? hf_ver.get() : CURRENT_BLOCK_MAJOR_VERSION;
118 blk.minor_version = hf_ver ? hf_ver.get() : CURRENT_BLOCK_MINOR_VERSION;
119 blk.timestamp = timestamp;
120 blk.prev_id = prev_id;
121
122 blk.tx_hashes.reserve(tx_list.size());
123 BOOST_FOREACH(const transaction &tx, tx_list)
124 {
125 crypto::hash tx_hash;
126 get_transaction_hash(tx, tx_hash);
127 blk.tx_hashes.push_back(tx_hash);
128 }
129
130 uint64_t total_fee = 0;
131 size_t txs_weight = 0;
132 BOOST_FOREACH(auto& tx, tx_list)
133 {
134 uint64_t fee = 0;
135 bool r = get_tx_fee(tx, fee);
136 CHECK_AND_ASSERT_MES(r, false, "wrong transaction passed to construct_block");
137 total_fee += fee;
138 txs_weight += get_transaction_weight(tx);
139 }
140
142 size_t target_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
143 while (true)
144 {
145 if (!construct_miner_tx(height, misc_utils::median(block_weights), already_generated_coins, target_block_weight, total_fee, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), 10, hf_ver ? hf_ver.get() : 1))
146 return false;
147
148 size_t actual_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
149 if (target_block_weight < actual_block_weight)
150 {
151 target_block_weight = actual_block_weight;
152 }
153 else if (actual_block_weight < target_block_weight)
154 {
155 size_t delta = target_block_weight - actual_block_weight;
156 blk.miner_tx.extra.resize(blk.miner_tx.extra.size() + delta, 0);
157 actual_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
158 if (actual_block_weight == target_block_weight)
159 {
160 break;
161 }
162 else
163 {
164 CHECK_AND_ASSERT_MES(target_block_weight < actual_block_weight, false, "Unexpected block size");
165 delta = actual_block_weight - target_block_weight;
166 blk.miner_tx.extra.resize(blk.miner_tx.extra.size() - delta);
167 actual_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
168 if (actual_block_weight == target_block_weight)
169 {
170 break;
171 }
172 else
173 {
174 CHECK_AND_ASSERT_MES(actual_block_weight < target_block_weight, false, "Unexpected block size");
175 blk.miner_tx.extra.resize(blk.miner_tx.extra.size() + delta, 0);
176 target_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
177 }
178 }
179 }
180 else
181 {
182 break;
183 }
184 }
185
186 //blk.tree_root_hash = get_tx_tree_hash(blk);
187
188 // Nonce search...
189 blk.nonce = 0;
191 blk.timestamp++;
192
193 add_block(blk, txs_weight, block_weights, already_generated_coins, hf_ver ? hf_ver.get() : 1);
194
195 return true;
196}
197
199{
200 std::vector<size_t> block_weights;
201 std::list<cryptonote::transaction> tx_list;
202 return construct_block(blk, 0, null_hash, miner_acc, timestamp, 0, block_weights, tx_list);
203}
204
206 const cryptonote::account_base& miner_acc,
207 const std::list<cryptonote::transaction>& tx_list/* = std::list<cryptonote::transaction>()*/,
208 const boost::optional<uint8_t>& hf_ver)
209{
210 uint64_t height = boost::get<txin_gen>(blk_prev.miner_tx.vin.front()).height + 1;
211 crypto::hash prev_id = get_block_hash(blk_prev);
212 // Keep difficulty unchanged
213 uint64_t timestamp = blk_prev.timestamp + current_difficulty_window(hf_ver); // DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN;
214 uint64_t already_generated_coins = get_already_generated_coins(prev_id);
215 std::vector<size_t> block_weights;
217
218 return construct_block(blk, height, prev_id, miner_acc, timestamp, already_generated_coins, block_weights, tx_list, hf_ver);
219}
220
221bool test_generator::construct_block_manually(block& blk, const block& prev_block, const account_base& miner_acc,
222 int actual_params/* = bf_none*/, uint8_t major_ver/* = 0*/,
223 uint8_t minor_ver/* = 0*/, uint64_t timestamp/* = 0*/,
224 const crypto::hash& prev_id/* = crypto::hash()*/, const difficulty_type& diffic/* = 1*/,
225 const transaction& miner_tx/* = transaction()*/,
226 const std::vector<crypto::hash>& tx_hashes/* = std::vector<crypto::hash>()*/,
227 size_t txs_weight/* = 0*/, size_t max_outs/* = 0*/, uint8_t hf_version/* = 1*/)
228{
229 blk.major_version = actual_params & bf_major_ver ? major_ver : CURRENT_BLOCK_MAJOR_VERSION;
230 blk.minor_version = actual_params & bf_minor_ver ? minor_ver : CURRENT_BLOCK_MINOR_VERSION;
231 blk.timestamp = actual_params & bf_timestamp ? timestamp : prev_block.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN; // Keep difficulty unchanged
232 blk.prev_id = actual_params & bf_prev_id ? prev_id : get_block_hash(prev_block);
233 blk.tx_hashes = actual_params & bf_tx_hashes ? tx_hashes : std::vector<crypto::hash>();
234 max_outs = actual_params & bf_max_outs ? max_outs : 9999;
235 hf_version = actual_params & bf_hf_version ? hf_version : 1;
236
237 size_t height = get_block_height(prev_block) + 1;
238 uint64_t already_generated_coins = get_already_generated_coins(prev_block);
239 std::vector<size_t> block_weights;
241 if (actual_params & bf_miner_tx)
242 {
243 blk.miner_tx = miner_tx;
244 }
245 else
246 {
247 size_t current_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
248 // TODO: This will work, until size of constructed block is less then CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE
249 if (!construct_miner_tx(height, misc_utils::median(block_weights), already_generated_coins, current_block_weight, 0, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), max_outs, hf_version))
250 return false;
251 }
252
253 //blk.tree_root_hash = get_tx_tree_hash(blk);
254
255 difficulty_type a_diffic = actual_params & bf_diffic ? diffic : get_test_difficulty(hf_version);
256 fill_nonce(blk, a_diffic, height);
257
258 add_block(blk, txs_weight, block_weights, already_generated_coins, hf_version);
259
260 return true;
261}
262
264 const cryptonote::account_base& miner_acc,
265 const std::vector<crypto::hash>& tx_hashes, size_t txs_weight)
266{
267 return construct_block_manually(blk, prev_block, miner_acc, bf_tx_hashes, 0, 0, 0, crypto::hash(), 0, transaction(), tx_hashes, txs_weight);
268}
269
270namespace
271{
272 uint64_t get_inputs_amount(const vector<tx_source_entry> &s)
273 {
274 uint64_t r = 0;
275 BOOST_FOREACH(const tx_source_entry &e, s)
276 {
277 r += e.amount;
278 }
279
280 return r;
281 }
282}
283
284bool init_output_indices(map_output_idx_t& outs, std::map<uint64_t, std::vector<size_t> >& outs_mine, const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx, const cryptonote::account_base& from) {
285
286 BOOST_FOREACH (const block& blk, blockchain) {
287 vector<const transaction*> vtx;
288 vtx.push_back(&blk.miner_tx);
289
290 BOOST_FOREACH(const crypto::hash &h, blk.tx_hashes) {
291 const map_hash2tx_t::const_iterator cit = mtx.find(h);
292 if (mtx.end() == cit)
293 throw std::runtime_error("block contains an unknown tx hash");
294
295 vtx.push_back(cit->second);
296 }
297
298 //vtx.insert(vtx.end(), blk.);
299 // TODO: add all other txes
300 for (size_t i = 0; i < vtx.size(); i++) {
301 const transaction &tx = *vtx[i];
302
303 for (size_t j = 0; j < tx.vout.size(); ++j) {
304 const tx_out &out = tx.vout[j];
305
306 output_index oi(out.target, out.amount, boost::get<txin_gen>(*blk.miner_tx.vin.begin()).height, i, j, &blk, vtx[i]);
307 oi.set_rct(tx.version == 4);
308 oi.unlock_time = tx.unlock_time;
309 oi.is_coin_base = i == 0;
310
311 if (2 == out.target.which()) { // out_to_key
312 outs[out.amount].push_back(oi);
313 size_t tx_global_idx = outs[out.amount].size() - 1;
314 outs[out.amount][tx_global_idx].idx = tx_global_idx;
315 // Is out to me?
316 if (is_out_to_acc(from.get_keys(), boost::get<txout_to_key>(out.target), get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), j)) {
317 outs_mine[out.amount].push_back(tx_global_idx);
318 }
319 }
320 }
321 }
322 }
323
324 return true;
325}
326
327bool init_spent_output_indices(map_output_idx_t& outs, map_output_t& outs_mine, const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx, const cryptonote::account_base& from) {
328
329 BOOST_FOREACH (const map_output_t::value_type &o, outs_mine) {
330 for (size_t i = 0; i < o.second.size(); ++i) {
331 output_index &oi = outs[o.first][o.second[i]];
332
333 // construct key image for this output
335 keypair in_ephemeral;
336 crypto::public_key out_key = boost::get<txout_to_key>(oi.out).key;
337 std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
338 subaddresses[from.get_keys().m_account_address.m_spend_public_key] = {0,0};
339 generate_key_image_helper(from.get_keys(), subaddresses, out_key, get_tx_pub_key_from_extra(*oi.p_tx), get_additional_tx_pub_keys_from_extra(*oi.p_tx), oi.out_no, in_ephemeral, img, hw::get_device(("default")));
340
341 // lookup for this key image in the events vector
342 BOOST_FOREACH(auto& tx_pair, mtx) {
343 const transaction& tx = *tx_pair.second;
344 BOOST_FOREACH(const txin_v &in, tx.vin) {
345 if (typeid(txin_to_key) == in.type()) {
346 const txin_to_key &itk = boost::get<txin_to_key>(in);
347 if (itk.k_image == img) {
348 oi.spent = true;
349 }
350 }
351 }
352 }
353 }
354 }
355
356 return true;
357}
358
359bool fill_output_entries(std::vector<output_index>& out_indices, size_t sender_out, size_t nmix, size_t& real_entry_idx, std::vector<tx_source_entry::output_entry>& output_entries)
360{
361 if (out_indices.size() <= nmix)
362 return false;
363
364 bool sender_out_found = false;
365 size_t rest = nmix;
366 for (size_t i = 0; i < out_indices.size() && (0 < rest || !sender_out_found); ++i)
367 {
368 const output_index& oi = out_indices[i];
369 if (oi.spent)
370 continue;
371
372 bool append = false;
373 if (i == sender_out)
374 {
375 append = true;
376 sender_out_found = true;
377 real_entry_idx = output_entries.size();
378 }
379 else if (0 < rest)
380 {
381 --rest;
382 append = true;
383 }
384
385 if (append)
386 {
387 rct::key comm = oi.commitment();
388 const txout_to_key& otk = boost::get<txout_to_key>(oi.out);
389 output_entries.push_back(tx_source_entry::output_entry(oi.idx, rct::ctkey({rct::pk2rct(otk.key), comm})));
390 }
391 }
392
393 return 0 == rest && sender_out_found;
394}
395
396bool fill_tx_sources(std::vector<tx_source_entry>& sources, const std::vector<test_event_entry>& events,
397 const block& blk_head, const cryptonote::account_base& from, uint64_t amount, size_t nmix)
398{
399 map_output_idx_t outs;
400 map_output_t outs_mine;
401
402 std::vector<cryptonote::block> blockchain;
403 map_hash2tx_t mtx;
404 if (!find_block_chain(events, blockchain, mtx, get_block_hash(blk_head)))
405 return false;
406
407 if (!init_output_indices(outs, outs_mine, blockchain, mtx, from))
408 return false;
409
410 if (!init_spent_output_indices(outs, outs_mine, blockchain, mtx, from))
411 return false;
412
413 // Iterate in reverse is more efficiency
414 uint64_t sources_amount = 0;
415 bool sources_found = false;
416 BOOST_REVERSE_FOREACH(const map_output_t::value_type o, outs_mine)
417 {
418 for (size_t i = 0; i < o.second.size() && !sources_found; ++i)
419 {
420 size_t sender_out = o.second[i];
421 const output_index& oi = outs[o.first][sender_out];
422 if (oi.spent)
423 continue;
424 if (oi.rct)
425 continue;
426
428 ts.amount = oi.amount;
430 ts.real_out_tx_key = get_tx_pub_key_from_extra(*oi.p_tx); // incoming tx public key
431 size_t realOutput;
432 if (!fill_output_entries(outs[o.first], sender_out, nmix, realOutput, ts.outputs))
433 continue;
434
435 ts.real_output = realOutput;
436 ts.rct = false;
437 ts.mask = rct::identity(); // non-rct has identity mask by definition
438
440 for(auto & ot : ts.outputs)
441 ot.second.mask = comm;
442
443 sources.push_back(ts);
444
445 sources_amount += ts.amount;
446 sources_found = amount <= sources_amount;
447 }
448
449 if (sources_found)
450 break;
451 }
452
453 return sources_found;
454}
455
457 de.addr = to;
458 de.amount = amount;
459 return true;
460}
461
462map_txid_output_t::iterator block_tracker::find_out(const crypto::hash &txid, size_t out)
463{
464 return find_out(std::make_pair(txid, out));
465}
466
467map_txid_output_t::iterator block_tracker::find_out(const output_hasher &id)
468{
469 return m_map_outs.find(id);
470}
471
472void block_tracker::process(const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx)
473{
474 std::vector<const cryptonote::block*> blks;
475 blks.reserve(blockchain.size());
476
477 BOOST_FOREACH (const block& blk, blockchain) {
478 auto hsh = get_block_hash(blk);
479 auto it = m_blocks.find(hsh);
480 if (it == m_blocks.end()){
481 m_blocks[hsh] = blk;
482 }
483
484 blks.push_back(&m_blocks[hsh]);
485 }
486
487 process(blks, mtx);
488}
489
490void block_tracker::process(const std::vector<const cryptonote::block*>& blockchain, const map_hash2tx_t& mtx)
491{
492 BOOST_FOREACH (const block* blk, blockchain) {
493 vector<const transaction*> vtx;
494 vtx.push_back(&(blk->miner_tx));
495
496 BOOST_FOREACH(const crypto::hash &h, blk->tx_hashes) {
497 const map_hash2tx_t::const_iterator cit = mtx.find(h);
498 CHECK_AND_ASSERT_THROW_MES(mtx.end() != cit, "block contains an unknown tx hash");
499 vtx.push_back(cit->second);
500 }
501
502 for (size_t i = 0; i < vtx.size(); i++) {
503 process(blk, vtx[i], i);
504 }
505 }
506}
507
508void block_tracker::process(const block* blk, const transaction * tx, size_t i)
509{
510 for (size_t j = 0; j < tx->vout.size(); ++j) {
511 const tx_out &out = tx->vout[j];
512
513 if (typeid(cryptonote::txout_to_key) != out.target.type()) { // out_to_key
514 continue;
515 }
516
517 const uint64_t rct_amount = tx->version == 2 ? 0 : out.amount;
518 const output_hasher hid = std::make_pair(tx->hash, j);
519 auto it = find_out(hid);
520 if (it != m_map_outs.end()){
521 continue;
522 }
523
524 output_index oi(out.target, out.amount, boost::get<txin_gen>(blk->miner_tx.vin.front()).height, i, j, blk, tx);
525 oi.set_rct(tx->version == 2);
526 oi.idx = m_outs[rct_amount].size();
527 oi.unlock_time = tx->unlock_time;
528 oi.is_coin_base = tx->vin.size() == 1 && tx->vin.back().type() == typeid(cryptonote::txin_gen);
529
530 m_outs[rct_amount].push_back(oi);
531 m_map_outs.insert({hid, oi});
532 }
533}
534
535void block_tracker::global_indices(const cryptonote::transaction *tx, std::vector<uint64_t> &indices)
536{
537 indices.clear();
538
539 for(size_t j=0; j < tx->vout.size(); ++j){
540 auto it = find_out(tx->hash, j);
541 if (it != m_map_outs.end()){
542 indices.push_back(it->second.idx);
543 }
544 }
545}
546
547void block_tracker::get_fake_outs(size_t num_outs, uint64_t amount, uint64_t global_index, uint64_t cur_height, std::vector<get_outs_entry> &outs){
548 auto & vct = m_outs[amount];
549 const size_t n_outs = vct.size();
550
551 std::set<size_t> used;
552 std::vector<size_t> choices;
553 choices.resize(n_outs);
554 for(size_t i=0; i < n_outs; ++i) choices[i] = i;
555 shuffle(choices.begin(), choices.end(), std::default_random_engine(crypto::rand<unsigned>()));
556
557 size_t n_iters = 0;
558 ssize_t idx = -1;
559 outs.reserve(num_outs);
560 while(outs.size() < num_outs){
561 n_iters += 1;
562 idx = (idx + 1) % n_outs;
563 size_t oi_idx = choices[(size_t)idx];
564 CHECK_AND_ASSERT_THROW_MES((n_iters / n_outs) <= outs.size(), "Fake out pick selection problem");
565
566 auto & oi = vct[oi_idx];
567 if (oi.idx == global_index)
568 continue;
569 if (oi.out.type() != typeid(cryptonote::txout_to_key))
570 continue;
571 if (oi.unlock_time > cur_height)
572 continue;
573 if (used.find(oi_idx) != used.end())
574 continue;
575
576 rct::key comm = oi.commitment();
577 auto out = boost::get<txout_to_key>(oi.out);
578 auto item = std::make_tuple(oi.idx, out.key, comm);
579 outs.push_back(item);
580 used.insert(oi_idx);
581 }
582}
583
585{
586 ostringstream ss;
587 for (auto &m_out : m_outs)
588 {
589 auto & vct = m_out.second;
590 ss << m_out.first << " => |vector| = " << vct.size() << '\n';
591
592 for (const auto & oi : vct)
593 {
594 auto out = boost::get<txout_to_key>(oi.out);
595
596 ss << " idx: " << oi.idx
597 << ", rct: " << oi.rct
598 << ", etn: " << oi.amount
599 << ", key: " << dump_keys(out.key.data)
600 << ", msk: " << dump_keys(oi.comm.bytes)
601 << ", txid: " << dump_keys(oi.p_tx->hash.data)
602 << '\n';
603 }
604 }
605
606 return ss.str();
607}
608
609void block_tracker::dump_data(const std::string & fname)
610{
611 ofstream myfile;
612 myfile.open (fname);
613 myfile << dump_data();
614 myfile.close();
615}
616
617std::string dump_data(const cryptonote::transaction &tx)
618{
619 ostringstream ss;
620 ss << "msg: " << dump_keys(tx.rct_signatures.message.bytes)
621 << ", vin: ";
622
623 for(auto & in : tx.vin){
624 if (typeid(txin_to_key) == in.type()){
625 auto tk = boost::get<txin_to_key>(in);
626 std::vector<uint64_t> full_off;
627 int64_t last = -1;
628
629 ss << " i: " << tk.amount << " [";
630 for(auto ix : tk.key_offsets){
631 ss << ix << ", ";
632 if (last == -1){
633 last = ix;
634 full_off.push_back(ix);
635 } else {
636 last += ix;
637 full_off.push_back((uint64_t)last);
638 }
639 }
640
641 ss << "], full: [";
642 for(auto ix : full_off){
643 ss << ix << ", ";
644 }
645 ss << "]; ";
646
647 } else if (typeid(txin_gen) == in.type()){
648 ss << " h: " << boost::get<txin_gen>(in).height << ", ";
649 } else {
650 ss << " ?, ";
651 }
652 }
653
654 ss << ", mixring: \n";
655 for (const auto & row : tx.rct_signatures.mixRing){
656 for(auto cur : row){
657 ss << " (" << dump_keys(cur.dest.bytes) << ", " << dump_keys(cur.mask.bytes) << ")\n ";
658 }
659 ss << "; ";
660 }
661
662 return ss.str();
663}
664
666{
667 if (typeid(cryptonote::account_public_address) == inp.type()){
668 return boost::get<cryptonote::account_public_address>(inp);
669 } else if(typeid(cryptonote::account_keys) == inp.type()){
670 return boost::get<cryptonote::account_keys>(inp).m_account_address;
671 } else if (typeid(cryptonote::account_base) == inp.type()){
672 return boost::get<cryptonote::account_base>(inp).get_keys().m_account_address;
673 } else if (typeid(cryptonote::tx_destination_entry) == inp.type()){
674 return boost::get<cryptonote::tx_destination_entry>(inp).addr;
675 } else {
676 throw std::runtime_error("Unexpected type");
677 }
678}
679
684
686{
687 return inp.m_account_address;
688}
689
691{
692 return inp.get_keys().m_account_address;
693}
694
699
700uint64_t sum_amount(const std::vector<tx_destination_entry>& destinations)
701{
702 uint64_t amount = 0;
703 for(auto & cur : destinations){
704 amount += cur.amount;
705 }
706
707 return amount;
708}
709
710uint64_t sum_amount(const std::vector<cryptonote::tx_source_entry>& sources)
711{
712 uint64_t amount = 0;
713 for(auto & cur : sources){
714 amount += cur.amount;
715 }
716
717 return amount;
718}
719
720void fill_tx_destinations(const var_addr_t& from, const std::vector<tx_destination_entry>& dests,
721 uint64_t fee,
722 const std::vector<tx_source_entry> &sources,
723 std::vector<tx_destination_entry>& destinations,
724 bool always_change)
725
726{
727 destinations.clear();
728 uint64_t amount = sum_amount(dests);
729 std::copy(dests.begin(), dests.end(), std::back_inserter(destinations));
730
731 tx_destination_entry de_change;
732 uint64_t cache_back = get_inputs_amount(sources) - (amount + fee);
733
734 if (cache_back > 0 || always_change) {
735 if (!fill_tx_destination(de_change, get_address(from), cache_back <= 0 ? 0 : cache_back))
736 throw std::runtime_error("couldn't fill transaction cache back destination");
737 destinations.push_back(de_change);
738 }
739}
740
742 uint64_t amount, uint64_t fee,
743 const std::vector<tx_source_entry> &sources,
744 std::vector<tx_destination_entry>& destinations,
745 std::vector<tx_destination_entry>& destinations_pure,
746 bool always_change)
747{
748 destinations.clear();
749
751 if (!fill_tx_destination(de, to, amount))
752 throw std::runtime_error("couldn't fill transaction destination");
753 destinations.push_back(de);
754 destinations_pure.push_back(de);
755
756 tx_destination_entry de_change;
757 uint64_t cache_back = get_inputs_amount(sources) - (amount + fee);
758
759 if (cache_back > 0 || always_change) {
760 if (!fill_tx_destination(de_change, get_address(from), cache_back <= 0 ? 0 : cache_back))
761 throw std::runtime_error("couldn't fill transaction cache back destination");
762 destinations.push_back(de_change);
763 }
764}
765
767 uint64_t amount, uint64_t fee,
768 const std::vector<tx_source_entry> &sources,
769 std::vector<tx_destination_entry>& destinations, bool always_change)
770{
771 std::vector<tx_destination_entry> destinations_pure;
772 fill_tx_destinations(from, to, amount, fee, sources, destinations, destinations_pure, always_change);
773}
774
775void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& events, const block& blk_head,
777 uint64_t amount, uint64_t fee, size_t nmix, std::vector<tx_source_entry>& sources,
778 std::vector<tx_destination_entry>& destinations)
779{
780 sources.clear();
781 destinations.clear();
782
783 if (!fill_tx_sources(sources, events, blk_head, from, amount + fee, nmix))
784 throw std::runtime_error("couldn't fill transaction sources");
785
786 fill_tx_destinations(from, to, amount, fee, sources, destinations, false);
787}
788
789void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& events, const block& blk_head,
791 uint64_t amount, uint64_t fee, size_t nmix, std::vector<tx_source_entry>& sources,
792 std::vector<tx_destination_entry>& destinations)
793{
794 fill_tx_sources_and_destinations(events, blk_head, from, to.get_keys().m_account_address, amount, fee, nmix, sources, destinations);
795}
796
798{
799 blk.nonce = 0;
800 while (!miner::find_nonce_for_given_block(blk, diffic, height))
801 blk.timestamp++;
802}
803
805{
807 de.amount = amount;
808 de.addr = get_address(to);
809 de.is_subaddress = is_subaddr;
810 return de;
811}
812
813std::vector<cryptonote::tx_destination_entry> build_dsts(const var_addr_t& to1, bool sub1, uint64_t am1)
814{
815 std::vector<cryptonote::tx_destination_entry> res;
816 res.push_back(build_dst(to1, sub1, am1));
817 return res;
818}
819
820std::vector<cryptonote::tx_destination_entry> build_dsts(std::initializer_list<dest_wrapper_t> inps)
821{
822 std::vector<cryptonote::tx_destination_entry> res;
823 res.reserve(inps.size());
824 for(auto & c : inps){
825 res.push_back(build_dst(c.addr, c.is_subaddr, c.amount));
826 }
827 return res;
828}
829
830bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins,
831 const account_public_address& miner_address, transaction& tx, uint64_t fee,
832 keypair* p_txkey/* = 0*/)
833{
834 keypair txkey;
835 txkey = keypair::generate(hw::get_device("default"));
836 add_tx_pub_key_to_extra(tx, txkey.pub);
837
838 if (0 != p_txkey)
839 *p_txkey = txkey;
840
841 txin_gen in;
842 in.height = height;
843 tx.vin.push_back(in);
844
845 // This will work, until size of constructed block is less then CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE
846 uint64_t block_reward;
847 //Deal with premine implementation.
848 if (height == 1){block_reward = 1260000000000;}
849 else if (!get_block_reward(0, 0, already_generated_coins, block_reward, 1, height))
850 {
851 LOG_PRINT_L0("Block is too big");
852 return false;
853 }
854 block_reward += fee;
855
856 crypto::key_derivation derivation;
857 crypto::public_key out_eph_public_key;
858 crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
859 crypto::derive_public_key(derivation, 0, miner_address.m_spend_public_key, out_eph_public_key);
860
861 tx_out out;
862 out.amount = block_reward;
863 out.target = txout_to_key(out_eph_public_key);
864 tx.vout.push_back(out);
865
866 tx.version = 1;
868
869 return true;
870}
871
872bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote::transaction& tx, const cryptonote::block& blk_head,
873 const cryptonote::account_base& from, const var_addr_t& to, uint64_t amount,
874 uint64_t fee, size_t nmix, bool rct, rct::RangeProofType range_proof_type, int bp_version)
875{
876 vector<tx_source_entry> sources;
877 vector<tx_destination_entry> destinations;
878 fill_tx_sources_and_destinations(events, blk_head, from, get_address(to), amount, fee, nmix, sources, destinations);
879
880 return construct_tx_rct(from.get_keys(), sources, destinations, from.get_keys().m_account_address, std::vector<uint8_t>(), tx, 0, rct, range_proof_type, bp_version);
881}
882
883bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote::transaction& tx, const cryptonote::block& blk_head,
884 const cryptonote::account_base& from, std::vector<cryptonote::tx_destination_entry> destinations,
885 uint64_t fee, size_t nmix, bool rct, rct::RangeProofType range_proof_type, int bp_version)
886{
887 vector<tx_source_entry> sources;
888 vector<tx_destination_entry> destinations_all;
889 uint64_t amount = sum_amount(destinations);
890
891 if (!fill_tx_sources(sources, events, blk_head, from, amount + fee, nmix))
892 throw std::runtime_error("couldn't fill transaction sources");
893
894 fill_tx_destinations(from, destinations, fee, sources, destinations_all, false);
895
896 return construct_tx_rct(from.get_keys(), sources, destinations_all, get_address(from), std::vector<uint8_t>(), tx, 0, rct, range_proof_type, bp_version);
897}
898
900 const cryptonote::account_base& from, const var_addr_t& to, uint64_t amount,
901 std::vector<cryptonote::tx_source_entry> &sources,
902 uint64_t fee, bool rct, rct::RangeProofType range_proof_type, int bp_version)
903{
904 vector<tx_destination_entry> destinations;
905 fill_tx_destinations(from, get_address(to), amount, fee, sources, destinations, rct);
906 return construct_tx_rct(from.get_keys(), sources, destinations, get_address(from), std::vector<uint8_t>(), tx, 0, rct, range_proof_type, bp_version);
907}
908
910 const cryptonote::account_base& from,
911 const std::vector<cryptonote::tx_destination_entry>& destinations,
912 std::vector<cryptonote::tx_source_entry> &sources,
913 uint64_t fee, bool rct, rct::RangeProofType range_proof_type, int bp_version)
914{
915 vector<tx_destination_entry> all_destinations;
916 fill_tx_destinations(from, destinations, fee, sources, all_destinations, rct);
917 return construct_tx_rct(from.get_keys(), sources, all_destinations, get_address(from), std::vector<uint8_t>(), tx, 0, rct, range_proof_type, bp_version);
918}
919
920bool construct_tx_rct(const cryptonote::account_keys& sender_account_keys, std::vector<cryptonote::tx_source_entry>& sources, const std::vector<cryptonote::tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, cryptonote::transaction& tx, uint64_t unlock_time, bool rct, rct::RangeProofType range_proof_type, int bp_version)
921{
922 std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
923 subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0, 0};
924 crypto::secret_key tx_key;
925 std::vector<crypto::secret_key> additional_tx_keys;
926 std::vector<tx_destination_entry> destinations_copy = destinations;
927 rct::RCTConfig rct_config = {range_proof_type, bp_version};
928 return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, rct_config, nullptr);
929}
930
931transaction construct_tx_with_fee(std::vector<test_event_entry>& events, const block& blk_head,
932 const account_base& acc_from, const var_addr_t& to, uint64_t amount, uint64_t fee)
933{
934 transaction tx;
935 construct_tx_to_key(events, tx, blk_head, acc_from, to, amount, fee, 0);
936 events.push_back(tx);
937 return tx;
938}
939
940uint64_t get_balance(const cryptonote::account_base& addr, const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx) {
941 uint64_t res = 0;
942 std::map<uint64_t, std::vector<output_index> > outs;
943 std::map<uint64_t, std::vector<size_t> > outs_mine;
944
945 map_hash2tx_t confirmed_txs;
946 get_confirmed_txs(blockchain, mtx, confirmed_txs);
947
948 if (!init_output_indices(outs, outs_mine, blockchain, confirmed_txs, addr))
949 return false;
950
951 if (!init_spent_output_indices(outs, outs_mine, blockchain, confirmed_txs, addr))
952 return false;
953
954 BOOST_FOREACH (const map_output_t::value_type &o, outs_mine) {
955 for (size_t i = 0; i < o.second.size(); ++i) {
956 if (outs[o.first][o.second[i]].spent)
957 continue;
958
959 res += outs[o.first][o.second[i]].amount;
960 }
961 }
962
963 return res;
964}
965
966bool extract_hard_forks(const std::vector<test_event_entry>& events, v_hardforks_t& hard_forks)
967{
968 for(auto & ev : events)
969 {
970 if (typeid(event_replay_settings) == ev.type())
971 {
972 const auto & rep_settings = boost::get<event_replay_settings>(ev);
973 if (rep_settings.hard_forks)
974 {
975 const auto & hf = rep_settings.hard_forks.get();
976 std::copy(hf.begin(), hf.end(), std::back_inserter(hard_forks));
977 }
978 }
979 }
980
981 return !hard_forks.empty();
982}
983
984void get_confirmed_txs(const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx, map_hash2tx_t& confirmed_txs)
985{
986 std::unordered_set<crypto::hash> confirmed_hashes;
987 BOOST_FOREACH(const block& blk, blockchain)
988 {
989 BOOST_FOREACH(const crypto::hash& tx_hash, blk.tx_hashes)
990 {
991 confirmed_hashes.insert(tx_hash);
992 }
993 }
994
995 BOOST_FOREACH(const auto& tx_pair, mtx)
996 {
997 if (0 != confirmed_hashes.count(tx_pair.first))
998 {
999 confirmed_txs.insert(tx_pair);
1000 }
1001 }
1002}
1003
1004bool trim_block_chain(std::vector<cryptonote::block>& blockchain, const crypto::hash& tail){
1005 size_t cut = 0;
1006 bool found = true;
1007
1008 for(size_t i = 0; i < blockchain.size(); ++i){
1009 crypto::hash chash = get_block_hash(blockchain[i]);
1010 if (chash == tail){
1011 cut = i;
1012 found = true;
1013 break;
1014 }
1015 }
1016
1017 if (found && cut > 0){
1018 blockchain.erase(blockchain.begin(), blockchain.begin() + cut);
1019 }
1020
1021 return found;
1022}
1023
1024bool trim_block_chain(std::vector<const cryptonote::block*>& blockchain, const crypto::hash& tail){
1025 size_t cut = 0;
1026 bool found = true;
1027
1028 for(size_t i = 0; i < blockchain.size(); ++i){
1029 crypto::hash chash = get_block_hash(*blockchain[i]);
1030 if (chash == tail){
1031 cut = i;
1032 found = true;
1033 break;
1034 }
1035 }
1036
1037 if (found && cut > 0){
1038 blockchain.erase(blockchain.begin(), blockchain.begin() + cut);
1039 }
1040
1041 return found;
1042}
1043
1044uint64_t num_blocks(const std::vector<test_event_entry>& events)
1045{
1046 uint64_t res = 0;
1047 BOOST_FOREACH(const test_event_entry& ev, events)
1048 {
1049 if (typeid(block) == ev.type())
1050 {
1051 res += 1;
1052 }
1053 }
1054
1055 return res;
1056}
1057
1058cryptonote::block get_head_block(const std::vector<test_event_entry>& events)
1059{
1060 for(auto it = events.rbegin(); it != events.rend(); ++it)
1061 {
1062 auto &ev = *it;
1063 if (typeid(block) == ev.type())
1064 {
1065 return boost::get<block>(ev);
1066 }
1067 }
1068
1069 throw std::runtime_error("No block event");
1070}
1071
1072bool find_block_chain(const std::vector<test_event_entry>& events, std::vector<cryptonote::block>& blockchain, map_hash2tx_t& mtx, const crypto::hash& head) {
1073 std::unordered_map<crypto::hash, const block*> block_index;
1074 BOOST_FOREACH(const test_event_entry& ev, events)
1075 {
1076 if (typeid(block) == ev.type())
1077 {
1078 const block* blk = &boost::get<block>(ev);
1079 block_index[get_block_hash(*blk)] = blk;
1080 }
1081 else if (typeid(transaction) == ev.type())
1082 {
1083 const transaction& tx = boost::get<transaction>(ev);
1084 mtx[get_transaction_hash(tx)] = &tx;
1085 }
1086 }
1087
1088 bool b_success = false;
1089 crypto::hash id = head;
1090 for (auto it = block_index.find(id); block_index.end() != it; it = block_index.find(id))
1091 {
1092 blockchain.push_back(*it->second);
1093 id = it->second->prev_id;
1094 if (null_hash == id)
1095 {
1096 b_success = true;
1097 break;
1098 }
1099 }
1100 reverse(blockchain.begin(), blockchain.end());
1101
1102 return b_success;
1103}
1104
1105bool find_block_chain(const std::vector<test_event_entry>& events, std::vector<const cryptonote::block*>& blockchain, map_hash2tx_t& mtx, const crypto::hash& head) {
1106 std::unordered_map<crypto::hash, const block*> block_index;
1107 BOOST_FOREACH(const test_event_entry& ev, events)
1108 {
1109 if (typeid(block) == ev.type())
1110 {
1111 const block* blk = &boost::get<block>(ev);
1112 block_index[get_block_hash(*blk)] = blk;
1113 }
1114 else if (typeid(transaction) == ev.type())
1115 {
1116 const transaction& tx = boost::get<transaction>(ev);
1117 mtx[get_transaction_hash(tx)] = &tx;
1118 }
1119 }
1120
1121 bool b_success = false;
1122 crypto::hash id = head;
1123 for (auto it = block_index.find(id); block_index.end() != it; it = block_index.find(id))
1124 {
1125 blockchain.push_back(it->second);
1126 id = it->second->prev_id;
1127 if (null_hash == id)
1128 {
1129 b_success = true;
1130 break;
1131 }
1132 }
1133 reverse(blockchain.begin(), blockchain.end());
1134 return b_success;
1135}
1136
1137
1139{
1140 m_callbacks[cb_name] = cb;
1141}
1142bool test_chain_unit_base::verify(const std::string& cb_name, cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry> &events)
1143{
1144 auto cb_it = m_callbacks.find(cb_name);
1145 if(cb_it == m_callbacks.end())
1146 {
1147 LOG_ERROR("Failed to find callback " << cb_name);
1148 return false;
1149 }
1150 return cb_it->second(c, ev_index, events);
1151}
1152
1157
1158bool test_chain_unit_base::check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool /*tx_added*/, size_t /*event_index*/, const cryptonote::transaction& /*tx*/)
1159{
1160 return !tvc.m_verification_failed;
1161}
1162
1163bool test_chain_unit_base::check_tx_verification_context_array(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t /*tx_added*/, size_t /*event_index*/, const std::vector<cryptonote::transaction>& /*txs*/)
1164{
1165 for (const cryptonote::tx_verification_context &tvc: tvcs)
1166 if (tvc.m_verification_failed)
1167 return false;
1168 return true;
1169}
uint64_t height
void fill_tx_sources_and_destinations(const std::vector< test_event_entry > &events, const block &blk_head, const cryptonote::account_base &from, const cryptonote::account_public_address &to, uint64_t amount, uint64_t fee, size_t nmix, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations)
Definition chaingen.cpp:775
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
bool find_block_chain(const std::vector< test_event_entry > &events, std::vector< cryptonote::block > &blockchain, map_hash2tx_t &mtx, const crypto::hash &head)
std::vector< cryptonote::tx_destination_entry > build_dsts(const var_addr_t &to1, bool sub1, uint64_t am1)
Definition chaingen.cpp:813
bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins, const account_public_address &miner_address, transaction &tx, uint64_t fee, keypair *p_txkey)
Definition chaingen.cpp:830
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_rct(const cryptonote::account_keys &sender_account_keys, std::vector< cryptonote::tx_source_entry > &sources, const std::vector< cryptonote::tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, std::vector< uint8_t > extra, cryptonote::transaction &tx, uint64_t unlock_time, bool rct, rct::RangeProofType range_proof_type, int bp_version)
Definition chaingen.cpp:920
void fill_nonce(cryptonote::block &blk, const difficulty_type &diffic, uint64_t height)
Definition chaingen.cpp:797
bool init_spent_output_indices(map_output_idx_t &outs, map_output_t &outs_mine, const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx, const cryptonote::account_base &from)
Definition chaingen.cpp:327
bool init_output_indices(map_output_idx_t &outs, std::map< uint64_t, std::vector< size_t > > &outs_mine, const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx, const cryptonote::account_base &from)
Definition chaingen.cpp:284
transaction construct_tx_with_fee(std::vector< test_event_entry > &events, const block &blk_head, const account_base &acc_from, const var_addr_t &to, uint64_t amount, uint64_t fee)
Definition chaingen.cpp:931
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 trim_block_chain(std::vector< cryptonote::block > &blockchain, const crypto::hash &tail)
bool extract_hard_forks(const std::vector< test_event_entry > &events, v_hardforks_t &hard_forks)
Definition chaingen.cpp:966
bool fill_tx_sources(std::vector< tx_source_entry > &sources, const std::vector< test_event_entry > &events, const block &blk_head, const cryptonote::account_base &from, uint64_t amount, size_t nmix)
Definition chaingen.cpp:396
bool fill_output_entries(std::vector< output_index > &out_indices, size_t sender_out, size_t nmix, size_t &real_entry_idx, std::vector< tx_source_entry::output_entry > &output_entries)
Definition chaingen.cpp:359
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
uint64_t get_balance(const cryptonote::account_base &addr, const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx)
Definition chaingen.cpp:940
bool fill_tx_destination(tx_destination_entry &de, const cryptonote::account_public_address &to, uint64_t amount)
Definition chaingen.cpp:456
void get_confirmed_txs(const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx, map_hash2tx_t &confirmed_txs)
Definition chaingen.cpp:984
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
std::unordered_map< crypto::hash, const cryptonote::transaction * > map_hash2tx_t
Definition chaingen.h:163
uint64_t current_difficulty_window(const boost::optional< uint8_t > &hf_ver=boost::none)
Definition chaingen.h:410
std::map< uint64_t, std::vector< output_index > > map_output_idx_t
Definition chaingen.h:356
std::vector< std::pair< uint8_t, uint64_t > > v_hardforks_t
Definition chaingen.h:137
boost::variant< cryptonote::account_public_address, cryptonote::account_keys, cryptonote::account_base, cryptonote::tx_destination_entry > var_addr_t
Definition chaingen.h:362
std::string dump_keys(T *buff32)
Definition chaingen.h:271
void fill_nonce(cryptonote::block &blk, const cryptonote::difficulty_type &diffic, uint64_t height)
Definition chaingen.cpp:797
cryptonote::difficulty_type get_test_difficulty(const boost::optional< uint8_t > &hf_ver=boost::none)
Definition chaingen.h:409
std::pair< crypto::hash, size_t > output_hasher
Definition chaingen.h:353
std::map< uint64_t, std::vector< size_t > > map_output_t
Definition chaingen.h:355
void process(const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx)
Definition chaingen.cpp:472
void global_indices(const cryptonote::transaction *tx, std::vector< uint64_t > &indices)
Definition chaingen.cpp:535
void get_fake_outs(size_t num_outs, uint64_t amount, uint64_t global_index, uint64_t cur_height, std::vector< get_outs_entry > &outs)
Definition chaingen.cpp:547
map_output_idx_t m_outs
Definition chaingen.h:373
map_block_t m_blocks
Definition chaingen.h:375
std::string dump_data()
Definition chaingen.cpp:584
map_txid_output_t m_map_outs
Definition chaingen.h:374
map_txid_output_t::iterator find_out(const crypto::hash &txid, size_t out)
Definition chaingen.cpp:462
const account_keys & get_keys() const
Definition account.cpp:264
handles core cryptonote functionality
static bool find_nonce_for_given_block(block &bl, const difficulty_type &diffic, uint64_t height)
Definition miner.cpp:478
bool check_tx_verification_context(const cryptonote::tx_verification_context &tvc, bool, size_t, const cryptonote::transaction &)
boost::function< bool(cryptonote::core &c, size_t ev_index, const std::vector< test_event_entry > &events)> verify_callback
Definition chaingen.h:168
void register_callback(const std::string &cb_name, verify_callback cb)
bool check_block_verification_context(const cryptonote::block_verification_context &bvc, size_t event_idx, const cryptonote::block &)
bool check_tx_verification_context_array(const std::vector< cryptonote::tx_verification_context > &tvcs, size_t, size_t, const std::vector< cryptonote::transaction > &)
bool verify(const std::string &cb_name, cryptonote::core &c, size_t ev_index, const std::vector< test_event_entry > &events)
uint64_t get_already_generated_coins(const crypto::hash &blk_id) const
Definition chaingen.cpp:88
bool construct_block_manually(cryptonote::block &blk, const cryptonote::block &prev_block, const cryptonote::account_base &miner_acc, int actual_params=bf_none, uint8_t major_ver=0, uint8_t minor_ver=0, uint64_t timestamp=0, const crypto::hash &prev_id=crypto::hash(), const cryptonote::difficulty_type &diffic=1, const cryptonote::transaction &miner_tx=cryptonote::transaction(), const std::vector< crypto::hash > &tx_hashes=std::vector< crypto::hash >(), size_t txs_sizes=0, size_t max_outs=999, uint8_t hf_version=1)
Definition chaingen.cpp:221
void get_last_n_block_weights(std::vector< size_t > &block_weights, const crypto::hash &head, size_t n) const
Definition chaingen.cpp:78
void get_block_chain(std::vector< block_info > &blockchain, const crypto::hash &head, size_t n) const
Definition chaingen.cpp:60
bool construct_block(cryptonote::block &blk, uint64_t height, const crypto::hash &prev_id, const cryptonote::account_base &miner_acc, uint64_t timestamp, uint64_t already_generated_coins, std::vector< size_t > &block_weights, const std::list< cryptonote::transaction > &tx_list, const boost::optional< uint8_t > &hf_ver=boost::none)
Definition chaingen.cpp:112
void add_block(const cryptonote::block &blk, size_t tsx_size, std::vector< size_t > &block_weights, uint64_t already_generated_coins, uint8_t hf_version=1)
Definition chaingen.cpp:104
bool construct_block_manually_tx(cryptonote::block &blk, const cryptonote::block &prev_block, const cryptonote::account_base &miner_acc, const std::vector< crypto::hash > &tx_hashes, size_t txs_size)
Definition chaingen.cpp:263
#define CURRENT_BLOCK_MINOR_VERSION
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN
#define CURRENT_BLOCK_MAJOR_VERSION
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
const char * res
const char * inp
#define AUTO_VAL_INIT(v)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define LOG_ERROR(x)
Definition misc_log_ex.h:98
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
#define LOG_PRINT_L0(x)
Definition misc_log_ex.h:99
crypto namespace.
Definition crypto.cpp:58
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
POD_CLASS key_derivation
Definition crypto.h:101
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition crypto.h:272
POD_CLASS public_key
Definition crypto.h:79
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
Definition crypto.h:275
void rand(size_t N, uint8_t *bytes)
Definition crypto.h:209
POD_CLASS key_image
Definition crypto.h:105
POD_CLASS hash
Definition hash.h:50
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
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 generate_key_image_helper(const account_keys &ack, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
boost::multiprecision::uint128_t difficulty_type
Definition difficulty.h:43
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version, uint64_t current_block_height, network_type nettype)
bool is_out_to_acc(const account_keys &acc, const txout_to_key &out_key, const crypto::public_key &tx_pub_key, const std::vector< crypto::public_key > &additional_tx_pub_keys, size_t output_index)
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
bool get_tx_fee(const transaction &tx, uint64_t &fee)
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)
bool add_tx_pub_key_to_extra(transaction &tx, const crypto::public_key &tx_pub_key)
crypto::hash get_transaction_hash(const transaction &t)
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction &tx, const blobdata &extra_nonce, size_t max_outs, uint8_t hard_fork_version, network_type nettype)
std::string blobdata
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
type_vec_type median(std::vector< type_vec_type > &v)
device & get_device(const std::string &device_descriptor)
Definition device.cpp:95
key zeroCommit(etn_amount amount)
Definition rctOps.cpp:322
RangeProofType
Definition rctTypes.h:235
key identity()
Definition rctOps.h:73
STL namespace.
struct rule_list head
crypto::hash get_block_hash(uint64_t height)
signed __int64 int64_t
Definition stdint.h:135
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
account_public_address m_account_address
Definition account.h:43
std::vector< crypto::hash > tx_hashes
crypto::secret_key sec
static keypair generate(hw::device &hwdev)
crypto::public_key pub
bool is_subaddress
uint64_t amount
account_public_address addr
crypto::public_key real_out_tx_key
uint64_t amount
bool rct
size_t real_output
std::vector< output_entry > outputs
rct::key mask
std::pair< uint64_t, rct::ctkey > output_entry
size_t real_output_in_tx_index
crypto::key_image k_image
uint64_t amount
Definition chaingen.h:290
const cryptonote::transaction * p_tx
Definition chaingen.h:301
size_t out_no
Definition chaingen.h:293
bool is_coin_base
Definition chaingen.h:296
rct::key commitment() const
Definition chaingen.h:323
const cryptonote::txout_target_v out
Definition chaingen.h:289
size_t idx
Definition chaingen.h:294
uint64_t unlock_time
Definition chaingen.h:295
void set_rct(bool arct)
Definition chaingen.h:315
unsigned char bytes[32]
Definition rctTypes.h:86
crypto::hash chash
Definition main.cpp:47