aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/CMakeLists.txt8
-rw-r--r--src/cryptonote_core/blockchain.cpp169
-rw-r--r--src/cryptonote_core/blockchain.h16
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp14
-rw-r--r--src/cryptonote_core/cryptonote_core.h3
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp35
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h10
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