diff options
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r-- | src/cryptonote_core/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 169 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.h | 16 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 14 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.h | 3 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_tx_utils.cpp | 35 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_tx_utils.h | 10 |
7 files changed, 209 insertions, 46 deletions
diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 5f5d88356..e272b94f0 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -35,13 +35,7 @@ set(cryptonote_core_sources set(cryptonote_core_headers) -set(cryptonote_core_private_headers - blockchain_storage_boost_serialization.h - blockchain.h - cryptonote_core.h - tx_pool.h - tx_sanity_check.h - cryptonote_tx_utils.h) +monero_find_all_headers(cryptonote_core_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(cryptonote_core ${cryptonote_core_private_headers}) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 4eaca039c..0b6a3abf3 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1341,6 +1341,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: // one input, of type txin_gen, with height set to the block's height // correct miner tx unlock time // a non-overflowing tx amount (dubious necessity on this check) +// valid output types bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version) { LOG_PRINT_L3("Blockchain::" << __func__); @@ -1369,6 +1370,8 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, return false; } + CHECK_AND_ASSERT_MES(check_output_types(b.miner_tx, hf_version), false, "miner transaction has invalid output type(s) in block " << get_block_hash(b)); + return true; } //------------------------------------------------------------------ @@ -3044,12 +3047,14 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context // from v4, forbid invalid pubkeys if (hf_version >= 4) { for (const auto &o: tx.vout) { - if (o.target.type() == typeid(txout_to_key)) { - const txout_to_key& out_to_key = boost::get<txout_to_key>(o.target); - if (!crypto::check_key(out_to_key.key)) { - tvc.m_invalid_output = true; - return false; - } + crypto::public_key output_public_key; + if (!get_output_public_key(o, output_public_key)) { + tvc.m_invalid_output = true; + return false; + } + if (!crypto::check_key(output_public_key)) { + tvc.m_invalid_output = true; + return false; } } } @@ -3166,6 +3171,13 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context } } + // from v15, require view tags on outputs + if (!check_output_types(tx, hf_version)) + { + tvc.m_invalid_output = true; + return false; + } + return true; } //------------------------------------------------------------------ @@ -3710,11 +3722,24 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b if (version >= HF_VERSION_PER_BYTE_FEE) { lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi); - div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL); div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL); - assert(hi == 0); - lo /= 5; - return lo; + if (version >= HF_VERSION_2021_SCALING) + { + // min_fee_per_byte = round_up( 0.95 * block_reward * ref_weight / (fee_median^2) ) + // note: since hardfork HF_VERSION_2021_SCALING, fee_median (a.k.a. median_block_weight) equals effective long term median + div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL); + assert(hi == 0); + lo -= lo / 20; + return lo; + } + else + { + // min_fee_per_byte = 0.2 * block_reward * ref_weight / (min_penalty_free_zone * fee_median) + div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL); + assert(hi == 0); + lo /= 5; + return lo; + } } const uint64_t fee_base = version >= 5 ? DYNAMIC_FEE_PER_KB_BASE_FEE_V5 : DYNAMIC_FEE_PER_KB_BASE_FEE; @@ -3787,6 +3812,81 @@ bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const } //------------------------------------------------------------------ +void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, uint64_t base_reward, uint64_t Mnw, uint64_t Mlw, std::vector<uint64_t> &fees) const +{ + // variable names and calculations as per https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf + // from (earlier than) this fork, the base fee is per byte + const uint64_t Mfw = std::min(Mnw, Mlw); + + // 3 kB divided by something ? It's going to be either 0 or *very* quantized, so fold it into integer steps below + //const uint64_t Brlw = DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / Mfw; + + // constant.... equal to 0, unless floating point, so fold it into integer steps below + //const uint64_t Br = DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 + + //const uint64_t Fl = base_reward * Brlw / Mfw; fold Brlw from above + const uint64_t Fl = base_reward * /*Brlw*/ DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / (Mfw * Mfw); + + // fold Fl into this for better precision (and to match the test cases in the PDF) + // const uint64_t Fn = 4 * Fl; + const uint64_t Fn = 4 * base_reward * /*Brlw*/ DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / (Mfw * Mfw); + + // const uint64_t Fm = 16 * base_reward * Br / Mfw; fold Br from above + const uint64_t Fm = 16 * base_reward * DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / (CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 * Mfw); + + // const uint64_t Fp = 2 * base_reward / Mnw; + + // fold Br from above, move 4Fm in the max to decrease quantization effect + //const uint64_t Fh = 4 * Fm * std::max<uint64_t>(1, Mfw / (32 * DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT * Mnw / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5)); + const uint64_t Fh = std::max<uint64_t>(4 * Fm, 4 * Fm * Mfw / (32 * DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT * Mnw / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5)); + + fees.resize(4); + fees[0] = cryptonote::round_money_up(Fl, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); + fees[1] = cryptonote::round_money_up(Fn, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); + fees[2] = cryptonote::round_money_up(Fm, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); + fees[3] = cryptonote::round_money_up(Fh, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); +} + +void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees) const +{ + const uint8_t version = get_current_hard_fork_version(); + const uint64_t db_height = m_db->height(); + + // we want Mlw = median of max((min(Mbw, 1.7 * Ml), Zm), Ml / 1.7) + // Mbw: block weight for the last 99990 blocks, 0 for the next 10 + // Ml: penalty free zone (dynamic), aka long_term_median, aka median of max((min(Mb, 1.7 * Ml), Zm), Ml / 1.7) + // Zm: 300000 (minimum penalty free zone) + // + // So we copy the current rolling median state, add 10 (grace_blocks) zeroes to it, and get back Mlw + + epee::misc_utils::rolling_median_t<uint64_t> rm = m_long_term_block_weights_cache_rolling_median; + for (size_t i = 0; i < grace_blocks; ++i) + rm.insert(0); + const uint64_t Mlw_penalty_free_zone_for_wallet = std::max<uint64_t>(rm.median(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5); + + // Msw: median over [100 - grace blocks] past + [grace blocks] future blocks + CHECK_AND_ASSERT_THROW_MES(grace_blocks <= 100, "Grace blocks invalid In 2021 fee scaling estimate."); + std::vector<uint64_t> weights; + get_last_n_blocks_weights(weights, 100 - grace_blocks); + weights.reserve(100); + for (size_t i = 0; i < grace_blocks; ++i) + weights.push_back(0); + const uint64_t Msw_effective_short_term_median = std::max(epee::misc_utils::median(weights), Mlw_penalty_free_zone_for_wallet); + + const uint64_t Mnw = std::min(Msw_effective_short_term_median, 50 * Mlw_penalty_free_zone_for_wallet); + + uint64_t already_generated_coins = db_height ? m_db->get_block_already_generated_coins(db_height - 1) : 0; + uint64_t base_reward; + if (!get_block_reward(m_current_block_cumul_weight_limit / 2, 1, already_generated_coins, base_reward, version)) + { + MERROR("Failed to determine block reward, using placeholder " << print_money(BLOCK_REWARD_OVERESTIMATE) << " as a high bound"); + base_reward = BLOCK_REWARD_OVERESTIMATE; + } + + get_dynamic_base_fee_estimate_2021_scaling(grace_blocks, base_reward, Mnw, Mlw_penalty_free_zone_for_wallet, fees); +} + +//------------------------------------------------------------------ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const { const uint8_t version = get_current_hard_fork_version(); @@ -3798,6 +3898,13 @@ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW) grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1; + if (version >= HF_VERSION_2021_SCALING) + { + std::vector<uint64_t> fees; + get_dynamic_base_fee_estimate_2021_scaling(grace_blocks, fees); + return fees[0]; + } + const uint64_t min_block_weight = get_min_block_weight(version); std::vector<uint64_t> weights; get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks); @@ -3882,9 +3989,11 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, cons } // The original code includes a check for the output corresponding to this input - // to be a txout_to_key. This is removed, as the database does not store this info, - // but only txout_to_key outputs are stored in the DB in the first place, done in - // Blockchain*::add_output + // to be a txout_to_key. This is removed, as the database does not store this info. + // Only txout_to_key (and since HF_VERSION_VIEW_TAGS, txout_to_tagged_key) + // outputs are stored in the DB in the first place, done in Blockchain*::add_output. + // Additional type checks on outputs were also added via cryptonote::check_output_types + // and cryptonote::get_output_public_key (see Blockchain::check_tx_outputs). m_output_keys.push_back(rct::ctkey({rct::pk2rct(pubkey), commitment})); return true; @@ -4472,6 +4581,7 @@ bool Blockchain::check_blockchain_pruning() return m_db->check_pruning(); } //------------------------------------------------------------------ +// returns min(Mb, 1.7*Ml) as per https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf from HF_VERSION_LONG_TERM_BLOCK_WEIGHT uint64_t Blockchain::get_next_long_term_block_weight(uint64_t block_weight) const { PERF_TIMER(get_next_long_term_block_weight); @@ -4486,7 +4596,18 @@ uint64_t Blockchain::get_next_long_term_block_weight(uint64_t block_weight) cons uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks); uint64_t long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median); - uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5; + uint64_t short_term_constraint; + if (hf_version >= HF_VERSION_2021_SCALING) + { + // long_term_block_weight = block_weight bounded to range [long-term-median/1.7, long-term-median*1.7] + block_weight = std::max<uint64_t>(block_weight, long_term_effective_median_block_weight * 10 / 17); + short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 7 / 10; + } + else + { + // long_term_block_weight = block_weight bounded to range [0, long-term-median*1.4] + short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5; + } uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint); return long_term_block_weight; @@ -4528,7 +4649,11 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median); - uint64_t short_term_constraint = m_long_term_effective_median_block_weight + m_long_term_effective_median_block_weight * 2 / 5; + uint64_t short_term_constraint = m_long_term_effective_median_block_weight; + if (hf_version >= HF_VERSION_2021_SCALING) + short_term_constraint += m_long_term_effective_median_block_weight * 7 / 10; + else + short_term_constraint += m_long_term_effective_median_block_weight * 2 / 5; uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint); if (db_height == 1) @@ -4547,7 +4672,19 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW); uint64_t short_term_median = epee::misc_utils::median(weights); - uint64_t effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * m_long_term_effective_median_block_weight); + uint64_t effective_median_block_weight; + if (hf_version >= HF_VERSION_2021_SCALING) + { + // effective median = short_term_median bounded to range [long_term_median, 50*long_term_median], but it can't be smaller than the + // minimum penalty free zone (a.k.a. 'full reward zone') + effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(m_long_term_effective_median_block_weight, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * m_long_term_effective_median_block_weight); + } + else + { + // effective median = short_term_median bounded to range [0, 50*long_term_median], but it can't be smaller than the + // minimum penalty free zone (a.k.a. 'full reward zone') + effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * m_long_term_effective_median_block_weight); + } m_current_block_cumul_weight_median = effective_median_block_weight; } diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 5460d7761..7a94f6358 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -648,6 +648,22 @@ namespace cryptonote * @return the fee estimate */ uint64_t get_dynamic_base_fee_estimate(uint64_t grace_blocks) const; + void get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, uint64_t base_reward, uint64_t Mnw, uint64_t Mlw, std::vector<uint64_t> &fees) const; + + /** + * @brief get four levels of dynamic per byte fee estimate for the next few blocks + * + * The dynamic fee is based on the block weight in a past window, and + * the current block reward. It is expressed per byte, and is based on + * https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf + * This function calculates an estimate for a dynamic fee which will be + * valid for the next grace_blocks + * + * @param grace_blocks number of blocks we want the fee to be valid for + * + * @return the fee estimates (4 of them) + */ + void get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees) const; /** * @brief validate a transaction's fee diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 2d2b1cbcf..a78f5d673 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1177,7 +1177,8 @@ namespace cryptonote return false; } - if (!check_tx_inputs_ring_members_diff(tx)) + const uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version(); + if (!check_tx_inputs_ring_members_diff(tx, hf_version)) { MERROR_VER("tx uses duplicate ring members"); return false; @@ -1189,6 +1190,12 @@ namespace cryptonote return false; } + if (!check_output_types(tx, hf_version)) + { + MERROR_VER("tx does not use valid output type(s)"); + return false; + } + return true; } //----------------------------------------------------------------------------------------------- @@ -1295,10 +1302,9 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------- - bool core::check_tx_inputs_ring_members_diff(const transaction& tx) const + bool core::check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version) const { - const uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); - if (version >= 6) + if (hf_version >= 6) { for(const auto& in: tx.vin) { diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 2e5248c5d..0b36730b6 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -1012,10 +1012,11 @@ namespace cryptonote * @brief verify that each ring uses distinct members * * @param tx the transaction to check + * @param hf_version the hard fork version rules to use * * @return false if any ring uses duplicate members, true otherwise */ - bool check_tx_inputs_ring_members_diff(const transaction& tx) const; + bool check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version) const; /** * @brief verify that each input key image in a transaction is in diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 76192be5d..1d2024a05 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -149,12 +149,17 @@ namespace cryptonote r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key); CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")"); - txout_to_key tk; - tk.key = out_eph_public_key; + uint64_t amount = out_amounts[no]; + summary_amounts += amount; + + bool use_view_tags = hard_fork_version >= HF_VERSION_VIEW_TAGS; + crypto::view_tag view_tag; + if (use_view_tags) + crypto::derive_view_tag(derivation, no, view_tag); tx_out out; - summary_amounts += out.amount = out_amounts[no]; - out.target = tk; + cryptonote::set_tx_out(amount, out_eph_public_key, use_view_tags, view_tag, out); + tx.vout.push_back(out); } @@ -198,7 +203,7 @@ namespace cryptonote return addr.m_view_public_key; } //--------------------------------------------------------------- - 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) + 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, bool use_view_tags) { hw::device &hwdev = sender_account_keys.get_device(); @@ -406,17 +411,16 @@ namespace cryptonote { CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount); crypto::public_key out_eph_public_key; + crypto::view_tag view_tag; hwdev.generate_output_ephemeral_keys(tx.version,sender_account_keys, txkey_pub, tx_key, dst_entr, change_addr, output_index, need_additional_txkeys, additional_tx_keys, - additional_tx_public_keys, amount_keys, out_eph_public_key); + additional_tx_public_keys, amount_keys, out_eph_public_key, + use_view_tags, view_tag); tx_out out; - out.amount = dst_entr.amount; - txout_to_key tk; - tk.key = out_eph_public_key; - out.target = tk; + cryptonote::set_tx_out(dst_entr.amount, out_eph_public_key, use_view_tags, view_tag, out); tx.vout.push_back(out); output_index++; summary_outs_money += dst_entr.amount; @@ -546,7 +550,9 @@ namespace cryptonote } for (size_t i = 0; i < tx.vout.size(); ++i) { - destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key)); + crypto::public_key output_public_key; + get_output_public_key(tx.vout[i], output_public_key); + destinations.push_back(rct::pk2rct(output_public_key)); outamounts.push_back(tx.vout[i].amount); amount_out += tx.vout[i].amount; } @@ -607,7 +613,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - 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) + 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, bool use_view_tags) { hw::device &hwdev = sender_account_keys.get_device(); hwdev.open_tx(tx_key); @@ -627,7 +633,8 @@ namespace cryptonote } } - 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); + bool shuffle_outs = true; + 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, shuffle_outs, use_view_tags); hwdev.close_tx(); return r; } catch(...) { @@ -643,7 +650,7 @@ namespace cryptonote crypto::secret_key tx_key; std::vector<crypto::secret_key> additional_tx_keys; std::vector<tx_destination_entry> destinations_copy = destinations; - 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); + 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, false); } //--------------------------------------------------------------- bool generate_genesis_block( diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index be6a6d946..f4ffb98ff 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -119,21 +119,23 @@ namespace cryptonote //--------------------------------------------------------------- crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr); 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 = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool shuffle_outs = true); - 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 = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL); + 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 = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool shuffle_outs = true, bool use_view_tags = false); + 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 = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool use_view_tags = false); 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) ; + crypto::public_key &out_eph_public_key, + const bool use_view_tags, crypto::view_tag &view_tag) ; 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) ; + crypto::public_key &out_eph_public_key, + const bool use_view_tags, crypto::view_tag &view_tag) ; bool generate_genesis_block( block& bl |