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));
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);
329 bool add_dummy_payment_id =
true;
337 LOG_PRINT_L2(
"Adding cleartext payment ID to extra nonce. Encrypted PIDs are now deprecated." << payment_id8);
341 memcpy(payment_id.data, payment_id8.data, 8);
342 memset(payment_id.data + 8, 0, 24);
348 LOG_ERROR(
"Failed to add payment id to tx extra");
352 add_dummy_payment_id =
false;
356 add_dummy_payment_id =
false;
361 if (destinations.size() > 2)
362 add_dummy_payment_id =
false;
364 if (add_dummy_payment_id)
372 LOG_ERROR(
"Failed to add dummy payment id to tx extra");
379 MWARNING(
"Failed to parse tx extra");
380 tx_extra_fields.clear();
383 struct input_generation_context_data
387 std::vector<input_generation_context_data> in_contexts;
396 if (src_entr.real_output >= src_entr.outputs.size()) {
397 LOG_ERROR(
"real_output index (" << src_entr.real_output <<
")bigger than output_keys.size()=" 398 << src_entr.outputs.size());
401 summary_inputs_etn += src_entr.amount;
404 in_contexts.push_back(input_generation_context_data());
406 keypair &in_ephemeral = in_contexts.back().in_ephemeral;
408 const auto &out_key =
reinterpret_cast<const crypto::public_key &
>(src_entr.outputs[src_entr.real_output].second.dest);
410 src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index,
411 in_ephemeral, img, hwdev, account_major_offset)) {
412 LOG_ERROR(
"Key image generation failed!");
417 if (!msout && !(in_ephemeral.
pub == src_entr.outputs[src_entr.real_output].second.dest)) {
418 LOG_ERROR(
"derived public key mismatch with output public key at index " 419 << idx <<
", real out " 420 << src_entr.real_output <<
"! " 421 <<
ENDL <<
"derived_key:" 424 <<
"real output_public_key:" 427 LOG_ERROR(
"amount " << src_entr.amount <<
", rct " << src_entr.rct);
428 LOG_ERROR(
"tx pubkey " << src_entr.real_out_tx_key <<
", real_output_in_tx_index " 429 << src_entr.real_output_in_tx_index);
435 input_to_key.
amount = src_entr.amount;
436 input_to_key.
k_image = msout ? rct::rct2ki(src_entr.multisig_kLRki.ki) : img;
440 input_to_key.
key_offsets.push_back(out_entry.first);
443 tx.
vin.push_back(input_to_key);
447 std::vector<size_t> ins_order(sources.size());
448 for (
size_t n = 0; n < sources.size(); ++n)
450 std::sort(ins_order.begin(), ins_order.end(), [&](
const size_t i0,
const size_t i1) {
453 return memcmp(&tk0.
k_image, &tk1.k_image,
sizeof(tk0.
k_image)) > 0;
456 std::swap(tx.
vin[i0], tx.
vin[i1]);
457 std::swap(in_contexts[i0], in_contexts[i1]);
458 std::swap(sources[i0], sources[i1]);
463 std::shuffle(destinations.begin(), destinations.end(), std::default_random_engine(crypto::rand<unsigned int>()));
468 summary_inputs_etn += src_entr.amount;
471 input.
amount = src_entr.amount;
472 input.
tx_hash = src_entr.tx_hash;
475 tx.
vin.push_back(input);
480 size_t num_stdaddresses = 0;
481 size_t num_subaddresses = 0;
483 classify_addresses(destinations, change_addr, num_stdaddresses, num_subaddresses, single_dest_subaddress);
487 if (num_stdaddresses == 0 && num_subaddresses == 1)
493 txkey_pub = rct::rct2pk(hwdev.
scalarmultBase(rct::sk2rct(tx_key)));
498 std::vector<crypto::public_key> additional_tx_public_keys;
503 bool need_additional_txkeys = num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1);
504 if (need_additional_txkeys)
505 CHECK_AND_ASSERT_MES(destinations.size() == additional_tx_keys.size(),
false,
"Wrong amount of additional tx keys");
516 need_additional_txkeys, additional_tx_keys,
517 additional_tx_public_keys, amount_keys, out_eph_public_key);
520 out.amount = dst_entr.amount;
522 tk.
key = out_eph_public_key;
524 tx.
vout.push_back(out);
526 summary_outs_etn += dst_entr.
amount;
529 out.amount = dst_entr.amount;
537 tx.
vout.push_back(out);
539 summary_outs_etn += dst_entr.
amount;
543 CHECK_AND_ASSERT_MES(additional_tx_public_keys.size() == additional_tx_keys.size(),
false,
"Internal error creating additional public keys");
548 if (need_additional_txkeys)
551 for (
size_t i = 0; i < additional_tx_public_keys.size(); ++i)
560 if(summary_outs_etn > summary_inputs_etn )
562 LOG_ERROR(
"Transaction inputs ETN ("<< summary_inputs_etn <<
") less than outputs ETN (" << summary_outs_etn <<
")");
567 bool zero_secret_key =
true;
572 MDEBUG(
"Null secret key, skipping signatures");
579 std::stringstream ss_ring_s;
586 ss_ring_s <<
"pub_keys:" <<
ENDL;
587 std::vector<const crypto::public_key *> keys_ptrs;
588 std::vector<crypto::public_key> keys(src_entr.outputs.size());
591 keys[ii] = rct2pk(o.second.dest);
592 keys_ptrs.push_back(&keys[ii]);
593 ss_ring_s << o.second.dest <<
ENDL;
597 tx.
signatures.push_back(std::vector<crypto::signature>());
598 std::vector<crypto::signature> &sigs = tx.
signatures.back();
599 sigs.resize(src_entr.outputs.size());
600 if (!zero_secret_key)
602 in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
603 ss_ring_s <<
"signatures:" <<
ENDL;
604 std::for_each(sigs.begin(), sigs.end(), [&](
const crypto::signature &s) { ss_ring_s << s <<
ENDL; });
605 ss_ring_s <<
"prefix_hash:" << tx_prefix_hash <<
ENDL <<
"in_ephemeral_key: " 606 << in_contexts[i].in_ephemeral.sec <<
ENDL <<
"real_output: " << src_entr.real_output <<
ENDL;
618 std::vector<crypto::signature> signature_vec;
619 if (!zero_secret_key) {
625 if (input_subaddress_index.
major == 0 && input_subaddress_index.
minor == 0) {
630 input_subaddress_index);
632 private_spend_for_sig);
638 private_view_for_sig,
639 private_spend_for_sig,
656 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)
662 size_t num_stdaddresses = 0;
663 size_t num_subaddresses = 0;
665 classify_addresses(destinations, change_addr, num_stdaddresses, num_subaddresses, single_dest_subaddress);
666 bool need_additional_txkeys = num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1);
667 if (need_additional_txkeys)
669 additional_tx_keys.clear();
670 for (
const auto &d: destinations)
671 additional_tx_keys.push_back(keypair::generate(sender_account_keys.
get_device()).sec);
674 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);
684 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)
686 std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
689 std::vector<crypto::secret_key> additional_tx_keys;
690 std::vector<tx_destination_entry> destinations_copy = destinations;
691 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);
701 bl = boost::value_initialized<block>();
705 std::vector<size_t> sz;
721 miner::find_nonce_for_given_block(bl, 1, 0);
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
const config_t & get_config(network_type nettype)
virtual bool scalarmultKey(rct::key &aP, const rct::key &P, const rct::key &a)=0
void set_null_besides_version()
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
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
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)
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
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 add_bridge_smartchain_address_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &bridge_smartchain_address)
bool add_bridge_source_address_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &bridge_source_address)
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)
SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx) SECP256K1_ARG_NONNULL(1)
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)
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
cryptonote::account_public_address address
std::vector< uint64_t > key_offsets
bool add_additional_tx_pub_keys_to_extra(std::vector< uint8_t > &tx_extra, const std::vector< crypto::public_key > &additional_pub_keys)
#define SECP256K1_CONTEXT_SIGN
void copy(key &AA, const key &A)
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
void hash_to_point(const crypto::hash &h, crypto::ec_point &res)
std::vector< uint8_t > extra
#define ETN_MINED_ETN_UNLOCK_WINDOW_V8
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)
std::vector< tx_out > vout
#define SECP256K1_EC_UNCOMPRESSED
Holds cryptonote related classes and helpers.
struct secp256k1_context_struct secp256k1_context
std::vector< txin_v > vin
blobdata tx_to_blob(const transaction &tx)
mdb_size_t count(MDB_cursor *cur)
crypto::public_key m_spend_public_key
bool add_tx_pub_key_to_extra(transaction &tx, const crypto::public_key &tx_pub_key)
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)
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
crypto::public_key m_view_public_key
virtual crypto::secret_key get_subaddress_private_spendkey(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &subaddr_index)=0
const crypto::public_key null_pkey
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)
std::vector< uint64_t > absolute_output_offsets_to_relative(const std::vector< uint64_t > &off)
device & get_device(const std::string &device_descriptor)
std::string obj_to_json_str(T &obj)
unsigned __int64 uint64_t
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
bool get_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash &payment_id)
virtual bool open_tx(crypto::secret_key &tx_key)=0
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 parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
virtual bool close_tx(void)=0
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata &extra_nonce, crypto::hash8 &payment_id)
crypto::secret_key m_view_secret_key
uint64_t const BASE_REWARD_CLAMP_THRESHOLD
std::vector< std::vector< crypto::signature > > signatures
account_public_address m_account_address
uint64_t const DEFAULT_DUST_THRESHOLD
bool sort_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< uint8_t > &sorted_tx_extra, bool allow_partial)
virtual bool scalarmultBase(rct::key &aG, const rct::key &a)=0
crypto::public_key get_destination_view_key_pub(const std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr)
void * memcpy(void *a, const void *b, size_t c)
crypto::secret_key m_spend_secret_key
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
#define HF_VERSION_PUBLIC_TX
crypto::key_image k_image
crypto::hash get_transaction_hash(const transaction &t)
bool remove_field_from_tx_extra(std::vector< uint8_t > &tx_extra, const std::type_info &type)
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
uint64_t m_address_prefix
void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen)
#define CURRENT_BLOCK_MINOR_VERSION
virtual bool get_transaction_prefix_hash(const cryptonote::transaction_prefix &tx, crypto::hash &tx_prefix_hash)=0
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
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
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)
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
hw::device & get_device() const
SECP256K1_API secp256k1_context * secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT
virtual crypto::secret_key get_subaddress_private_viewkey(const crypto::secret_key &main_wallet_sec_view, crypto::secret_key &subaddress_sec_spend)=0
#define CURRENT_BLOCK_MAJOR_VERSION