32#include <unordered_set>
48#include <boost/algorithm/hex.hpp>
55 void classify_addresses(
const std::vector<tx_destination_entry> &destinations,
const boost::optional<cryptonote::account_public_address>& change_addr,
size_t &num_stdaddresses,
size_t &num_subaddresses,
account_public_address &single_dest_subaddress)
59 std::unordered_set<cryptonote::account_public_address> unique_dst_addresses;
62 if (change_addr && dst_entr.addr == change_addr)
64 if (unique_dst_addresses.count(dst_entr.addr) == 0)
66 unique_dst_addresses.insert(dst_entr.addr);
67 if (dst_entr.is_subaddress)
70 single_dest_subaddress = dst_entr.addr;
78 LOG_PRINT_L2(
"destinations include " << num_stdaddresses <<
" standard addresses and " << num_subaddresses <<
" subaddresses");
81 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) {
90 if(!
get_block_reward(median_weight, current_block_weight, already_generated_coins, block_reward, hard_fork_version,
height, nettype))
96#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
97 LOG_PRINT_L1(
"Creating block template: reward " << block_reward <<
108 if (hard_fork_version >= 2 && hard_fork_version < 4) {
112 std::vector<uint64_t> out_amounts;
114 [&out_amounts](
uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
115 [&out_amounts](
uint64_t a_dust) { out_amounts.push_back(a_dust); });
118 if (
height == 0 || hard_fork_version >= 4)
121 while (max_outs < out_amounts.size())
125 out_amounts[1] += out_amounts[0];
126 for (
size_t n = 1; n < out_amounts.size(); ++n)
127 out_amounts[n - 1] = out_amounts[n];
128 out_amounts.pop_back();
139 for (
const auto out_amount : out_amounts)
147 summary_amounts += out.amount = out_amount;
149 tx.
vout.push_back(out);
158 if(!extra_nonce.empty())
164 for (
size_t no = 0; no < out_amounts.size(); no++)
175 tk.
key = out_eph_public_key;
178 summary_amounts += out.amount = out_amounts[no];
180 tx.
vout.push_back(out);
187 CHECK_AND_ASSERT_MES(summary_amounts == block_reward,
false,
"Failed to construct miner tx, summary_amounts = " << summary_amounts <<
" not equal block_reward = " << block_reward);
191 tx.
vin.push_back(in);
204 for (
const auto &i : destinations)
208 if (change_addr && i.addr == *change_addr)
217 if (count == 0 && change_addr)
218 return change_addr->m_view_public_key;
222 bool construct_tx_with_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,
const crypto::secret_key &tx_key,
const std::vector<crypto::secret_key> &additional_tx_keys,
bool rct,
const rct::RCTConfig &rct_config,
rct::multisig_out *msout,
bool shuffle_outs,
const uint32_t account_major_offset,
const cryptonote::network_type nettype)
232 std::vector<rct::key> amount_keys;
248 std::vector<tx_extra_field> tx_extra_fields;
263 std::copy(std::begin(point.data), std::end(point.data), std::begin(portal_address_spendkey.data));
265 std::string portal_address_viewkey_hex_str;
267 portal_address_viewkey_hex_str =
"2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375";
269 portal_address_viewkey_hex_str =
"5866666666666666666666666666666666666666666666666666666666666666";
283 if(dest_address == portal_address){
291 LOG_PRINT_L1(
"Source address: " << bridge_source_address);
294 unsigned char seckey1[32];
295 unsigned char public_key64[65];
307 LOG_ERROR(
"Failed to create secp256k1 public key");
318 keccak(public_key64 + 1, 64, pubkey1.
data, 32);
322 std::string bridge_smartchain_address =
"0x" + hex_address;
323 LOG_PRINT_L1(
"Smartchain address: " << bridge_smartchain_address);
330 std::string sig_message = bridge_source_address + bridge_smartchain_address;
336 LOG_PRINT_L1(
"Bridge ownership signature added to tx_extra");
339 bool add_dummy_payment_id =
true;
347 LOG_PRINT_L2(
"Adding cleartext payment ID to extra nonce. Encrypted PIDs are now deprecated." << payment_id8);
349 std::string extra_nonce;
351 memcpy(payment_id.data, payment_id8.data, 8);
352 memset(payment_id.data + 8, 0, 24);
358 LOG_ERROR(
"Failed to add payment id to tx extra");
362 add_dummy_payment_id =
false;
366 add_dummy_payment_id =
false;
371 if (destinations.size() > 2)
372 add_dummy_payment_id =
false;
374 if (add_dummy_payment_id)
376 std::string extra_nonce;
382 LOG_ERROR(
"Failed to add dummy payment id to tx extra");
389 MWARNING(
"Failed to parse tx extra");
390 tx_extra_fields.clear();
393 struct input_generation_context_data
397 std::vector<input_generation_context_data> in_contexts;
406 if (src_entr.real_output >= src_entr.outputs.size()) {
407 LOG_ERROR(
"real_output index (" << src_entr.real_output <<
")bigger than output_keys.size()="
408 << src_entr.outputs.size());
411 summary_inputs_etn += src_entr.amount;
414 in_contexts.push_back(input_generation_context_data());
416 keypair &in_ephemeral = in_contexts.back().in_ephemeral;
418 const auto &out_key =
reinterpret_cast<const crypto::public_key &
>(src_entr.outputs[src_entr.real_output].second.dest);
420 src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index,
421 in_ephemeral, img, hwdev, account_major_offset)) {
422 LOG_ERROR(
"Key image generation failed!");
427 if (!msout && !(in_ephemeral.
pub == src_entr.outputs[src_entr.real_output].second.dest)) {
428 LOG_ERROR(
"derived public key mismatch with output public key at index "
429 << idx <<
", real out "
430 << src_entr.real_output <<
"! "
431 <<
ENDL <<
"derived_key:"
434 <<
"real output_public_key:"
437 LOG_ERROR(
"amount " << src_entr.amount <<
", rct " << src_entr.rct);
438 LOG_ERROR(
"tx pubkey " << src_entr.real_out_tx_key <<
", real_output_in_tx_index "
439 << src_entr.real_output_in_tx_index);
445 input_to_key.
amount = src_entr.amount;
446 input_to_key.
k_image = msout ? rct::rct2ki(src_entr.multisig_kLRki.ki) : img;
450 input_to_key.
key_offsets.push_back(out_entry.first);
453 tx.
vin.push_back(input_to_key);
457 std::vector<size_t> ins_order(sources.size());
458 for (
size_t n = 0; n < sources.size(); ++n)
460 std::sort(ins_order.begin(), ins_order.end(), [&](
const size_t i0,
const size_t i1) {
461 const txin_to_key &tk0 = boost::get<txin_to_key>(tx.vin[i0]);
462 const txin_to_key &tk1 = boost::get<txin_to_key>(tx.vin[i1]);
463 return memcmp(&tk0.k_image, &tk1.k_image, sizeof(tk0.k_image)) > 0;
466 std::swap(tx.
vin[i0], tx.
vin[i1]);
467 std::swap(in_contexts[i0], in_contexts[i1]);
468 std::swap(sources[i0], sources[i1]);
478 summary_inputs_etn += src_entr.amount;
481 input.
amount = src_entr.amount;
482 input.
tx_hash = src_entr.tx_hash;
485 tx.
vin.push_back(input);
490 size_t num_stdaddresses = 0;
491 size_t num_subaddresses = 0;
493 classify_addresses(destinations, change_addr, num_stdaddresses, num_subaddresses, single_dest_subaddress);
497 if (num_stdaddresses == 0 && num_subaddresses == 1)
503 txkey_pub = rct::rct2pk(hwdev.
scalarmultBase(rct::sk2rct(tx_key)));
508 std::vector<crypto::public_key> additional_tx_public_keys;
513 bool need_additional_txkeys = num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1);
514 if (need_additional_txkeys)
515 CHECK_AND_ASSERT_MES(destinations.size() == additional_tx_keys.size(),
false,
"Wrong amount of additional tx keys");
526 need_additional_txkeys, additional_tx_keys,
527 additional_tx_public_keys, amount_keys, out_eph_public_key);
530 out.amount = dst_entr.amount;
532 tk.
key = out_eph_public_key;
534 tx.
vout.push_back(out);
536 summary_outs_etn += dst_entr.
amount;
539 out.amount = dst_entr.amount;
547 tx.
vout.push_back(out);
549 summary_outs_etn += dst_entr.
amount;
553 CHECK_AND_ASSERT_MES(additional_tx_public_keys.size() == additional_tx_keys.size(),
false,
"Internal error creating additional public keys");
558 if (need_additional_txkeys)
561 for (
size_t i = 0; i < additional_tx_public_keys.size(); ++i)
570 if(summary_outs_etn > summary_inputs_etn )
572 LOG_ERROR(
"Transaction inputs ETN ("<< summary_inputs_etn <<
") less than outputs ETN (" << summary_outs_etn <<
")");
577 bool zero_secret_key =
true;
582 MDEBUG(
"Null secret key, skipping signatures");
589 std::stringstream ss_ring_s;
596 ss_ring_s <<
"pub_keys:" <<
ENDL;
597 std::vector<const crypto::public_key *> keys_ptrs;
598 std::vector<crypto::public_key> keys(src_entr.outputs.size());
601 keys[ii] = rct2pk(o.second.dest);
602 keys_ptrs.push_back(&keys[ii]);
603 ss_ring_s << o.second.dest <<
ENDL;
607 tx.
signatures.push_back(std::vector<crypto::signature>());
608 std::vector<crypto::signature> &sigs = tx.
signatures.back();
609 sigs.resize(src_entr.outputs.size());
610 if (!zero_secret_key)
612 in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
613 ss_ring_s <<
"signatures:" <<
ENDL;
614 std::for_each(sigs.begin(), sigs.end(), [&](
const crypto::signature &s) { ss_ring_s << s << ENDL; });
615 ss_ring_s <<
"prefix_hash:" << tx_prefix_hash <<
ENDL <<
"in_ephemeral_key: "
616 << in_contexts[i].in_ephemeral.sec <<
ENDL <<
"real_output: " << src_entr.real_output <<
ENDL;
628 std::vector<crypto::signature> signature_vec;
629 if (!zero_secret_key) {
635 if (input_subaddress_index.
major == 0 && input_subaddress_index.
minor == 0) {
640 input_subaddress_index);
642 private_spend_for_sig);
648 private_view_for_sig,
649 private_spend_for_sig,
666 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)
672 size_t num_stdaddresses = 0;
673 size_t num_subaddresses = 0;
675 classify_addresses(destinations, change_addr, num_stdaddresses, num_subaddresses, single_dest_subaddress);
676 bool need_additional_txkeys = num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1);
677 if (need_additional_txkeys)
679 additional_tx_keys.clear();
680 for (
const auto &d: destinations)
684 bool r =
construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys,
rct, rct_config, msout,
true, account_major_offset, nettype);
694 bool construct_tx(
const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources,
const 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)
696 std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
699 std::vector<crypto::secret_key> additional_tx_keys;
700 std::vector<tx_destination_entry> destinations_copy = destinations;
701 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,
false, {
rct::RangeProofBorromean, 0}, NULL);
706 , std::string
const & genesis_tx
711 bl = boost::value_initialized<block>();
715 std::vector<size_t> sz;
720 std::string genesis_coinbase_tx_hex = genesis_tx;
static bool find_nonce_for_given_block(block &bl, const difficulty_type &diffic, uint64_t height)
void set_null_besides_version()
std::vector< uint8_t > extra
std::vector< txin_v > vin
std::vector< tx_out > vout
std::vector< std::vector< crypto::signature > > signatures
virtual crypto::secret_key get_subaddress_private_viewkey(const crypto::secret_key &main_wallet_sec_view, crypto::secret_key &subaddress_sec_spend)=0
virtual bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key, const cryptonote::tx_destination_entry &dst_entr, const boost::optional< cryptonote::account_public_address > &change_addr, const size_t output_index, const bool &need_additional_txkeys, const std::vector< crypto::secret_key > &additional_tx_keys, std::vector< crypto::public_key > &additional_tx_public_keys, std::vector< rct::key > &amount_keys, crypto::public_key &out_eph_public_key)=0
virtual bool get_transaction_prefix_hash(const cryptonote::transaction_prefix &tx, crypto::hash &tx_prefix_hash)=0
virtual bool scalarmultBase(rct::key &aG, const rct::key &a)=0
virtual bool open_tx(crypto::secret_key &tx_key)=0
virtual bool generate_ring_signature(const crypto::hash &prefix_hash, const crypto::key_image &image, const std::vector< const crypto::public_key * > &pubs, const crypto::secret_key &sec, std::size_t sec_index, crypto::signature *sig)=0
virtual crypto::secret_key get_subaddress_private_spendkey(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &subaddr_index)=0
virtual bool generate_input_signature(const crypto::hash &prefix_hash, const uint32_t input_index, const crypto::secret_key sec_view, const crypto::secret_key sec_spend, crypto::signature &signature)=0
virtual bool close_tx(void)=0
virtual bool scalarmultKey(rct::key &aP, const rct::key &P, const rct::key &a)=0
#define HF_VERSION_PUBLIC_TX
#define CURRENT_BLOCK_MINOR_VERSION
#define ETN_MINED_ETN_UNLOCK_WINDOW_V8
#define CURRENT_BLOCK_MAJOR_VERSION
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
void * memcpy(void *a, const void *b, size_t c)
void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
uint64_t const DEFAULT_DUST_THRESHOLD
uint64_t const BASE_REWARD_CLAMP_THRESHOLD
const crypto::public_key null_pkey
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
void cn_fast_hash(const void *data, size_t length, char *hash)
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
void hash_to_point(const crypto::hash &h, crypto::ec_point &res)
void rand(size_t N, uint8_t *bytes)
Holds cryptonote related classes and helpers.
std::string obj_to_json_str(T &obj)
bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, const std::vector< uint8_t > &extra, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, const uint32_t account_major_offset, const cryptonote::network_type nettype)
void classify_addresses(const std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, size_t &num_stdaddresses, size_t &num_subaddresses, account_public_address &single_dest_subaddress)
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)
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 add_bridge_ownership_sig_to_tx_extra(std::vector< uint8_t > &tx_extra, const crypto::signature &sig)
bool sort_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< uint8_t > &sorted_tx_extra, bool allow_partial)
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash8 &payment_id)
void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t &chunk_handler, const dust_handler_t &dust_handler)
bool get_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash &payment_id)
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
crypto::public_key get_destination_view_key_pub(const std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr)
std::vector< uint64_t > absolute_output_offsets_to_relative(const std::vector< uint64_t > &off)
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
bool add_bridge_smartchain_address_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &bridge_smartchain_address)
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 find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
bool construct_tx(const account_keys &sender_account_keys, std::vector< tx_source_entry > &sources, const 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)
bool construct_tx_with_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, const crypto::secret_key &tx_key, const std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, bool shuffle_outs, const uint32_t account_major_offset, const cryptonote::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)
blobdata tx_to_blob(const transaction &tx)
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
bool add_additional_tx_pub_keys_to_extra(std::vector< uint8_t > &tx_extra, const std::vector< crypto::public_key > &additional_pub_keys)
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
bool remove_field_from_tx_extra(std::vector< uint8_t > &tx_extra, const std::type_info &type)
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
const config_t & get_config(network_type nettype)
bool add_bridge_source_address_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &bridge_source_address)
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
device & get_device(const std::string &device_descriptor)
SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx) SECP256K1_ARG_NONNULL(1)
#define SECP256K1_CONTEXT_SIGN
struct secp256k1_context_struct secp256k1_context
SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(const secp256k1_context *ctx, const unsigned char *seckey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2)
SECP256K1_API secp256k1_context * secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
#define SECP256K1_EC_UNCOMPRESSED
unsigned __int64 uint64_t
crypto::secret_key m_view_secret_key
hw::device & get_device() const
crypto::secret_key m_spend_secret_key
account_public_address m_account_address
crypto::public_key m_view_public_key
crypto::public_key m_spend_public_key
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX
static keypair generate(hw::device &hwdev)
std::pair< uint64_t, rct::ctkey > output_entry
crypto::key_image k_image
std::vector< uint64_t > key_offsets
uint64_t m_address_prefix
cryptonote::account_public_address address