From e373a2037b10681ca72d38b1777af5f4ec77ba38 Mon Sep 17 00:00:00 2001
From: kenshi84 <kenshi84@protonmail.ch>
Date: Mon, 16 Oct 2017 13:08:44 +0900
Subject: [PATCH 1/2] performance_tests: add master spend pubkey to subaddress
 hashtable

---
 tests/performance_tests/is_out_to_acc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/performance_tests/is_out_to_acc.h b/tests/performance_tests/is_out_to_acc.h
index 7da061c1e..c31897628 100644
--- a/tests/performance_tests/is_out_to_acc.h
+++ b/tests/performance_tests/is_out_to_acc.h
@@ -64,6 +64,7 @@ public:
   {
     const cryptonote::txout_to_key& tx_out = boost::get<cryptonote::txout_to_key>(m_tx.vout[0].target);
     std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
+    subaddresses[m_bob.get_keys().m_account_address.m_spend_public_key] = {0,0};
     std::vector<crypto::key_derivation> additional_derivations;
     boost::optional<cryptonote::subaddress_receive_info> info = cryptonote::is_out_to_acc_precomp(subaddresses, tx_out.key, m_derivation, additional_derivations, 0);
     return (bool)info;

From 88ebfd646a5e75de0544958e88d152df86e310ec Mon Sep 17 00:00:00 2001
From: kenshi84 <kenshi84@protonmail.ch>
Date: Tue, 17 Oct 2017 08:45:00 +0900
Subject: [PATCH 2/2] core_tests: fix for subaddress patch

---
 src/cryptonote_core/cryptonote_tx_utils.cpp    | 10 +++++-----
 src/cryptonote_core/cryptonote_tx_utils.h      |  4 ++--
 tests/core_tests/block_validation.cpp          |  4 ++--
 tests/core_tests/chaingen.cpp                  |  2 +-
 tests/core_tests/double_spend.inl              |  2 +-
 tests/core_tests/integer_overflow.cpp          |  5 +++--
 tests/core_tests/transaction_tests.cpp         |  2 +-
 tests/core_tests/v2_tests.cpp                  |  2 +-
 tests/performance_tests/ge_frombytes_vartime.h |  2 +-
 9 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index 586df9079..96f6ee872 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -158,7 +158,7 @@ namespace cryptonote
     return destinations[0].addr.m_view_public_key;
   }
   //---------------------------------------------------------------
-  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, const std::vector<tx_destination_entry>& destinations, const cryptonote::account_public_address& change_addr, 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)
+  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, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, 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)
   {
     if (destinations.empty())
     {
@@ -301,7 +301,7 @@ namespace cryptonote
     account_public_address single_dest_subaddress;
     for(const tx_destination_entry& dst_entr: destinations)
     {
-      if (dst_entr.addr == change_addr)
+      if (change_addr && dst_entr.addr == *change_addr)
         continue;
       if (unique_dst_addresses.count(dst_entr.addr) == 0)
       {
@@ -354,7 +354,7 @@ namespace cryptonote
       }
 
       bool r;
-      if (dst_entr.addr == change_addr)
+      if (change_addr && dst_entr.addr == *change_addr)
       {
         // sending change to yourself; derivation = a*R
         r = crypto::generate_key_derivation(txkey.pub, sender_account_keys.m_view_secret_key, derivation);
@@ -565,13 +565,13 @@ namespace cryptonote
     return true;
   }
   //---------------------------------------------------------------
-  bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)
+  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, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)
   {
      std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
      subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0};
      crypto::secret_key tx_key;
      std::vector<crypto::secret_key> additional_tx_keys;
-     return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations, destinations.back().addr, extra, tx, unlock_time, tx_key, additional_tx_keys);
+     return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys);
   }
   //---------------------------------------------------------------
   bool generate_genesis_block(
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index b5de44b88..9a3b2484d 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -73,8 +73,8 @@ namespace cryptonote
 
   //---------------------------------------------------------------
   crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys);
-  bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
-  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, const std::vector<tx_destination_entry>& destinations, const cryptonote::account_public_address& change_addr, 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);
+  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, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
+  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, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, 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);
 
   bool generate_genesis_block(
       block& bl
diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp
index 527059141..db44cd279 100644
--- a/tests/core_tests/block_validation.cpp
+++ b/tests/core_tests/block_validation.cpp
@@ -350,7 +350,7 @@ bool gen_block_miner_tx_has_2_in::generate(std::vector<test_event_entry>& events
   destinations.push_back(de);
 
   transaction tmp_tx;
-  if (!construct_tx(miner_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tmp_tx, 0))
+  if (!construct_tx(miner_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tmp_tx, 0))
     return false;
 
   MAKE_MINER_TX_MANUALLY(miner_tx, blk_0);
@@ -393,7 +393,7 @@ bool gen_block_miner_tx_with_txin_to_key::generate(std::vector<test_event_entry>
   destinations.push_back(de);
 
   transaction tmp_tx;
-  if (!construct_tx(miner_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tmp_tx, 0))
+  if (!construct_tx(miner_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tmp_tx, 0))
     return false;
 
   MAKE_MINER_TX_MANUALLY(miner_tx, blk_1);
diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp
index f23aa8ecb..2b713cab9 100644
--- a/tests/core_tests/chaingen.cpp
+++ b/tests/core_tests/chaingen.cpp
@@ -563,7 +563,7 @@ bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote
   vector<tx_destination_entry> destinations;
   fill_tx_sources_and_destinations(events, blk_head, from, to, amount, fee, nmix, sources, destinations);
 
-  return construct_tx(from.get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0);
+  return construct_tx(from.get_keys(), sources, destinations, from.get_keys().m_account_address, std::vector<uint8_t>(), tx, 0);
 }
 
 transaction construct_tx_with_fee(std::vector<test_event_entry>& events, const block& blk_head,
diff --git a/tests/core_tests/double_spend.inl b/tests/core_tests/double_spend.inl
index 438e39e47..bf63503ae 100644
--- a/tests/core_tests/double_spend.inl
+++ b/tests/core_tests/double_spend.inl
@@ -144,7 +144,7 @@ bool gen_double_spend_in_tx<txs_keeped_by_block>::generate(std::vector<test_even
   destinations.push_back(de);
 
   cryptonote::transaction tx_1;
-  if (!construct_tx(bob_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_1, 0))
+  if (!construct_tx(bob_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_1, 0))
     return false;
 
   SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, txs_keeped_by_block);
diff --git a/tests/core_tests/integer_overflow.cpp b/tests/core_tests/integer_overflow.cpp
index 3ac55c073..5a9604fc1 100644
--- a/tests/core_tests/integer_overflow.cpp
+++ b/tests/core_tests/integer_overflow.cpp
@@ -65,6 +65,7 @@ namespace
     se.real_output = 0;
     se.rct = false;
     se.real_out_tx_key = get_tx_pub_key_from_extra(tx);
+    se.real_out_additional_tx_keys = get_additional_tx_pub_keys_from_extra(tx);
     se.real_output_in_tx_index = out_idx;
 
     sources.push_back(se);
@@ -175,7 +176,7 @@ bool gen_uint_overflow_2::generate(std::vector<test_event_entry>& events) const
   destinations.push_back(tx_destination_entry(sources.front().amount - MONEY_SUPPLY - MONEY_SUPPLY + 1 - TESTS_DEFAULT_FEE, bob_addr, false));
 
   cryptonote::transaction tx_1;
-  if (!construct_tx(miner_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_1, 0))
+  if (!construct_tx(miner_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_1, 0))
     return false;
   events.push_back(tx_1);
 
@@ -201,7 +202,7 @@ bool gen_uint_overflow_2::generate(std::vector<test_event_entry>& events) const
   destinations.push_back(de);
 
   cryptonote::transaction tx_2;
-  if (!construct_tx(bob_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_2, 0))
+  if (!construct_tx(bob_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_2, 0))
     return false;
   events.push_back(tx_2);
 
diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp
index dcba36e80..00c602103 100644
--- a/tests/core_tests/transaction_tests.cpp
+++ b/tests/core_tests/transaction_tests.cpp
@@ -108,7 +108,7 @@ bool test_transaction_generation_and_ring_signature()
   destinations.push_back(td);
 
   transaction tx_rc1;
-  bool r = construct_tx(miner_acc2.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_rc1, 0);
+  bool r = construct_tx(miner_acc2.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_rc1, 0);
   CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
 
   crypto::hash pref_hash = get_transaction_prefix_hash(tx_rc1);
diff --git a/tests/core_tests/v2_tests.cpp b/tests/core_tests/v2_tests.cpp
index f1256cb64..6c94ac76c 100644
--- a/tests/core_tests/v2_tests.cpp
+++ b/tests/core_tests/v2_tests.cpp
@@ -108,7 +108,7 @@ bool gen_v2_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
   destinations.push_back(td);
 
   transaction tx;
-  bool r = construct_tx(miner_accounts[0].get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0);
+  bool r = construct_tx(miner_accounts[0].get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0);
   CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
   if (!valid)
     DO_CALLBACK(events, "mark_invalid_tx");
diff --git a/tests/performance_tests/ge_frombytes_vartime.h b/tests/performance_tests/ge_frombytes_vartime.h
index a5e64aeb2..ea72fcd26 100644
--- a/tests/performance_tests/ge_frombytes_vartime.h
+++ b/tests/performance_tests/ge_frombytes_vartime.h
@@ -54,7 +54,7 @@ public:
     std::vector<tx_destination_entry> destinations;
     destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false));
 
-    return construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, std::vector<uint8_t>(), m_tx, 0);
+    return construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, boost::none, std::vector<uint8_t>(), m_tx, 0);
   }
 
   bool test()