Electroneum
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"
49 #include "cryptonote_basic/miner.h"
50 
51 #include "chaingen.h"
52 #include "device/device.hpp"
53 using namespace std;
54 
55 using namespace epee;
56 using namespace crypto;
57 using namespace cryptonote;
58 
59 
60 void 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 
78 void 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 
104 void 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 
141  blk.miner_tx = AUTO_VAL_INIT(blk.miner_tx);
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;
190  while (!miner::find_nonce_for_given_block(blk, get_test_difficulty(hf_ver), height))
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;
216  get_last_n_block_weights(block_weights, prev_id, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
217 
218  return construct_block(blk, height, prev_id, miner_acc, timestamp, already_generated_coins, block_weights, tx_list, hf_ver);
219 }
220 
221 bool 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;
240  get_last_n_block_weights(block_weights, get_block_hash(prev_block), CRYPTONOTE_REWARD_BLOCKS_WINDOW);
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 
270 namespace
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 
284 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) {
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 
327 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) {
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
334  crypto::key_image img;
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 
359 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)
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 
396 bool 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 
439  rct::key comm = rct::zeroCommit(ts.amount);
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 
462 map_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 
467 map_txid_output_t::iterator block_tracker::find_out(const output_hasher &id)
468 {
469  return m_map_outs.find(id);
470 }
471 
472 void 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 
490 void 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 
508 void 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 
535 void 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 
547 void 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 
610 {
611  ofstream myfile;
612  myfile.open (fname);
613  myfile << dump_data();
614  myfile.close();
615 }
616 
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 
681 {
682  return inp;
683 }
684 
686 {
687  return inp.m_account_address;
688 }
689 
691 {
692  return inp.get_keys().m_account_address;
693 }
694 
696 {
697  return inp.addr;
698 }
699 
700 uint64_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 
710 uint64_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 
720 void 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 
775 void 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 
789 void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& events, const block& blk_head,
790  const cryptonote::account_base& from, const cryptonote::account_base& to,
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 
813 std::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 
820 std::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 
830 bool 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 
872 bool 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 
883 bool 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 
920 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)
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 
931 transaction 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 
940 uint64_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 
966 bool 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 
984 void 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 
1004 bool 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 
1024 bool 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 
1044 uint64_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 
1058 cryptonote::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 
1072 bool 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 
1105 bool 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 }
1142 bool 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 
1154 {
1155  return !bvc.m_verification_failed;
1156 }
1157 
1158 bool 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 
1163 bool 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 }
const char * res
Definition: hmac_keccak.cpp:41
std::map< uint64_t, std::vector< output_index > > map_output_idx_t
Definition: chaingen.h:356
crypto::public_key pub
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
size_t idx
Definition: chaingen.h:294
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
std::vector< crypto::hash > tx_hashes
bool get_tx_fee(const transaction &tx, uint64_t &fee)
crypto::public_key real_out_tx_key
void global_indices(const cryptonote::transaction *tx, std::vector< uint64_t > &indices)
Definition: chaingen.cpp:535
bool extract_hard_forks(const std::vector< test_event_entry > &events, v_hardforks_t &hard_forks)
Definition: chaingen.cpp:966
const char * inp
Definition: hmac_keccak.cpp:40
bool check_tx_verification_context(const cryptonote::tx_verification_context &tvc, bool, size_t, const cryptonote::transaction &)
Definition: chaingen.cpp:1158
bool check_block_verification_context(const cryptonote::block_verification_context &bvc, size_t event_idx, const cryptonote::block &)
Definition: chaingen.cpp:1153
uint64_t current_difficulty_window(const boost::optional< uint8_t > &hf_ver=boost::none)
Definition: chaingen.h:410
crypto::secret_key sec
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
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
::std::string string
Definition: gtest-port.h:1097
bool is_coin_base
Definition: chaingen.h:296
POD_CLASS key_derivation
Definition: crypto.h:98
bool find_block_chain(const std::vector< test_event_entry > &events, std::vector< cryptonote::block > &blockchain, map_hash2tx_t &mtx, const crypto::hash &head)
Definition: chaingen.cpp:1072
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
crypto::hash chash
Definition: main.cpp:47
uint64_t height
Definition: blockchain.cpp:91
const cryptonote::txout_target_v out
Definition: chaingen.h:289
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
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
std::vector< cryptonote::tx_destination_entry > build_dsts(const var_addr_t &to1, bool sub1, uint64_t am1)
Definition: chaingen.cpp:813
uint64_t sum_amount(const std::vector< tx_destination_entry > &destinations)
Definition: chaingen.cpp:700
std::map< uint64_t, std::vector< size_t > > map_output_t
Definition: chaingen.h:355
uint64_t num_blocks(const std::vector< test_event_entry > &events)
Definition: chaingen.cpp:1044
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
const char * key
Definition: hmac_keccak.cpp:39
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
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
crypto namespace.
Definition: crypto.cpp:58
STL namespace.
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
boost::function< bool(cryptonote::core &c, size_t ev_index, const std::vector< test_event_entry > &events)> verify_callback
Definition: chaingen.h:168
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 rct
boost::variant< cryptonote::account_public_address, cryptonote::account_keys, cryptonote::account_base, cryptonote::tx_destination_entry > var_addr_t
Definition: chaingen.h:362
unsigned char uint8_t
Definition: stdint.h:124
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
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
uint64_t amount
cryptonote::tx_destination_entry build_dst(const var_addr_t &to, bool is_subaddr, uint64_t amount)
Definition: chaingen.cpp:804
bool check_tx_verification_context_array(const std::vector< cryptonote::tx_verification_context > &tvcs, size_t, size_t, const std::vector< cryptonote::transaction > &)
Definition: chaingen.cpp:1163
uint64_t amount
Definition: chaingen.h:290
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
void get_confirmed_txs(const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx, map_hash2tx_t &confirmed_txs)
Definition: chaingen.cpp:984
void copy(key &AA, const key &A)
Definition: rctOps.h:79
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
size_t real_output
tuple make_tuple()
Definition: gtest-tuple.h:675
map_txid_output_t::iterator find_out(const crypto::hash &txid, size_t out)
Definition: chaingen.cpp:462
std::vector< uint8_t > extra
bool fill_tx_destination(tx_destination_entry &de, const cryptonote::account_public_address &to, uint64_t amount)
Definition: chaingen.cpp:456
const account_keys & get_keys() const
Definition: account.cpp:264
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
bool trim_block_chain(std::vector< cryptonote::block > &blockchain, const crypto::hash &tail)
Definition: chaingen.cpp:1004
bool spent
Definition: chaingen.h:297
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
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 add_tx_pub_key_to_extra(transaction &tx, const crypto::public_key &tx_pub_key)
void set_rct(bool arct)
Definition: chaingen.h:315
uint64_t unlock_time
Definition: chaingen.h:295
std::unordered_map< crypto::hash, const cryptonote::transaction * > map_hash2tx_t
Definition: chaingen.h:163
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
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)
const cryptonote::transaction * p_tx
Definition: chaingen.h:301
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
device & get_device(const std::string &device_descriptor)
Definition: device.cpp:95
handles core cryptonote functionality
unsigned __int64 uint64_t
Definition: stdint.h:136
std::string dump_data(const cryptonote::transaction &tx)
Definition: chaingen.cpp:617
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
uint64_t amount
bool is_subaddress
cryptonote::account_public_address get_address(const var_addr_t &inp)
Definition: chaingen.cpp:665
POD_CLASS public_key
Definition: crypto.h:76
account_public_address addr
void register_callback(const std::string &cb_name, verify_callback cb)
Definition: chaingen.cpp:1138
std::string blobdata
Definition: blobdatatype.h:39
type_vec_type median(std::vector< type_vec_type > &v)
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
size_t out_no
Definition: chaingen.h:293
account_public_address m_account_address
Definition: account.h:43
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)
unsigned char bytes[32]
Definition: rctTypes.h:86
key identity()
Definition: rctOps.h:73
std::pair< crypto::hash, size_t > output_hasher
Definition: chaingen.h:353
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
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
POD_CLASS key_image
Definition: crypto.h:102
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 fill_nonce(cryptonote::block &blk, const difficulty_type &diffic, uint64_t height)
Definition: chaingen.cpp:797
size_t real_output_in_tx_index
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
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
bool verify(const std::string &cb_name, cryptonote::core &c, size_t ev_index, const std::vector< test_event_entry > &events)
Definition: chaingen.cpp:1142
crypto::key_image k_image
crypto::hash get_transaction_hash(const transaction &t)
uint64_t get_already_generated_coins(const crypto::hash &blk_id) const
Definition: chaingen.cpp:88
signed __int64 int64_t
Definition: stdint.h:135
struct rule_list head
void process(const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx)
Definition: chaingen.cpp:472
std::vector< output_entry > outputs
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
#define CURRENT_BLOCK_MINOR_VERSION
key zeroCommit(etn_amount amount)
Definition: rctOps.cpp:322
crypto::hash get_block_hash(uint64_t height)
POD_CLASS hash
Definition: hash.h:50
cryptonote::difficulty_type get_test_difficulty(const boost::optional< uint8_t > &hf_ver=boost::none)
Definition: chaingen.h:409
#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN
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 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::pair< uint64_t, rct::ctkey > output_entry
RangeProofType
Definition: rctTypes.h:235
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
std::string dump_keys(T *buff32)
Definition: chaingen.h:271
std::string dump_data()
Definition: chaingen.cpp:584
cryptonote::block get_head_block(const std::vector< test_event_entry > &events)
Definition: chaingen.cpp:1058
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)
ctkeyM mixRing
Definition: rctTypes.h:243
void get_last_n_block_weights(std::vector< size_t > &block_weights, const crypto::hash &head, size_t n) const
Definition: chaingen.cpp:78
uint64_t get_block_height(const block &b)
void get_block_chain(std::vector< block_info > &blockchain, const crypto::hash &head, size_t n) const
Definition: chaingen.cpp:60
std::vector< std::pair< uint8_t, uint64_t > > v_hardforks_t
Definition: chaingen.h:137
#define CURRENT_BLOCK_MAJOR_VERSION
rct::key commitment() const
Definition: chaingen.h:323
rct::key mask