aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorj-berman <justinberman@protonmail.com>2021-11-15 05:23:53 -0800
committerj-berman <justinberman@protonmail.com>2022-04-18 00:49:53 -0700
commitea87b30f8907ee11252433811e7a7d0c46758cca (patch)
tree61dedf56a781a83285be092b078019bebdc94f2e /tests
parentMerge pull request #8207 (diff)
downloadmonero-ea87b30f8907ee11252433811e7a7d0c46758cca.tar.xz
Add view tags to outputs to reduce wallet scanning time
Implements view tags as proposed by @UkoeHB in MRL issue https://github.com/monero-project/research-lab/issues/73 At tx construction, the sender adds a 1-byte view tag to each output. The view tag is derived from the sender-receiver shared secret. When scanning for outputs, the receiver can check the view tag for a match, in order to reduce scanning time. When the view tag does not match, the wallet avoids the more expensive EC operations when deriving the output public key using the shared secret.
Diffstat (limited to 'tests')
-rw-r--r--tests/core_tests/block_validation.cpp124
-rw-r--r--tests/core_tests/block_validation.h34
-rw-r--r--tests/core_tests/chaingen.cpp22
-rw-r--r--tests/core_tests/chaingen.h9
-rw-r--r--tests/core_tests/chaingen_main.cpp13
-rw-r--r--tests/core_tests/rct.cpp108
-rw-r--r--tests/core_tests/rct.h70
-rw-r--r--tests/crypto/main.cpp10
-rw-r--r--tests/crypto/tests.txt56
-rw-r--r--tests/performance_tests/CMakeLists.txt1
-rw-r--r--tests/performance_tests/derive_view_tag.h62
-rw-r--r--tests/performance_tests/is_out_to_acc.h5
-rw-r--r--tests/performance_tests/main.cpp6
-rw-r--r--tests/performance_tests/out_can_be_to_acc.h103
14 files changed, 603 insertions, 20 deletions
diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp
index 28f1de7d0..711f67b41 100644
--- a/tests/core_tests/block_validation.cpp
+++ b/tests/core_tests/block_validation.cpp
@@ -671,3 +671,127 @@ bool gen_block_low_coinbase::generate(std::vector<test_event_entry>& events) con
return true;
}
+
+bool gen_block_miner_tx_out_has_no_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ bool use_view_tags = false;
+
+ BLOCK_VALIDATION_INIT_GENERATE();
+
+ MAKE_MINER_TX_MANUALLY(miner_tx, blk_0);
+
+ CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should not have a view tag");
+
+ crypto::public_key output_public_key;
+ crypto::view_tag view_tag;
+ cryptonote::get_output_public_key(miner_tx.vout[0], output_public_key);
+
+ // explicitly call the setter to ensure it does not set a view tag on the miner tx output
+ cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
+ CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should still not have a view tag");
+
+ block blk_1;
+ generator.construct_block_manually(blk_1, blk_0, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx);
+ events.push_back(blk_1);
+
+ DO_CALLBACK(events, "check_block_accepted");
+
+ return true;
+}
+
+bool gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ bool use_view_tags = false;
+
+ BLOCK_VALIDATION_INIT_GENERATE();
+
+ keypair txkey;
+ MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(miner_tx, blk_0, HF_VERSION_VIEW_TAGS+1, &txkey);
+
+ crypto::public_key output_public_key;
+ crypto::view_tag view_tag;
+ cryptonote::get_output_public_key(miner_tx.vout[0], output_public_key);
+
+ // remove the view tag that is currently set on the miner tx output at this point
+ cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
+ CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should not have a view tag");
+
+ block blk_1;
+ generator.construct_block_manually(blk_1, blk_0, miner_account,
+ test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_miner_tx,
+ HF_VERSION_VIEW_TAGS+1, HF_VERSION_VIEW_TAGS+1, 0, crypto::hash(), 0, miner_tx);
+ events.push_back(blk_1);
+
+ DO_CALLBACK(events, "check_block_purged");
+
+ return true;
+}
+
+bool gen_block_miner_tx_out_has_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ bool use_view_tags = true;
+
+ BLOCK_VALIDATION_INIT_GENERATE();
+
+ keypair txkey;
+ MAKE_MINER_TX_AND_KEY_MANUALLY(miner_tx, blk_0, &txkey);
+
+ // derive the view tag for the miner tx output
+ crypto::key_derivation derivation;
+ crypto::public_key output_public_key;
+ crypto::view_tag view_tag;
+ crypto::generate_key_derivation(miner_account.get_keys().m_account_address.m_view_public_key, txkey.sec, derivation);
+ crypto::derive_public_key(derivation, 0, miner_account.get_keys().m_account_address.m_spend_public_key, output_public_key);
+ crypto::derive_view_tag(derivation, 0, view_tag);
+
+ // set the view tag on the miner tx output
+ cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
+ boost::optional<crypto::view_tag> actual_vt = cryptonote::get_output_view_tag(miner_tx.vout[0]);
+ CHECK_AND_ASSERT_MES(actual_vt && *actual_vt == view_tag, false, "unexpected output view tag");
+
+ block blk_1;
+ generator.construct_block_manually(blk_1, blk_0, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx);
+ events.push_back(blk_1);
+
+ DO_CALLBACK(events, "check_block_purged");
+
+ return true;
+}
+
+bool gen_block_miner_tx_out_has_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ bool use_view_tags = true;
+
+ BLOCK_VALIDATION_INIT_GENERATE();
+
+ keypair txkey;
+ MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(miner_tx, blk_0, HF_VERSION_VIEW_TAGS, &txkey);
+
+ CHECK_AND_ASSERT_MES(cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should have a view tag");
+
+ // derive the view tag for the miner tx output
+ crypto::key_derivation derivation;
+ crypto::public_key output_public_key;
+ crypto::view_tag view_tag;
+ crypto::generate_key_derivation(miner_account.get_keys().m_account_address.m_view_public_key, txkey.sec, derivation);
+ crypto::derive_public_key(derivation, 0, miner_account.get_keys().m_account_address.m_spend_public_key, output_public_key);
+ crypto::derive_view_tag(derivation, 0, view_tag);
+
+ boost::optional<crypto::view_tag> actual_vt = cryptonote::get_output_view_tag(miner_tx.vout[0]);
+ CHECK_AND_ASSERT_MES(actual_vt && *actual_vt == view_tag, false, "unexpected output view tag");
+
+ // set the view tag on the miner tx output
+ cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
+ boost::optional<crypto::view_tag> actual_vt_after_setting = cryptonote::get_output_view_tag(miner_tx.vout[0]);
+ CHECK_AND_ASSERT_MES(actual_vt_after_setting && *actual_vt_after_setting == view_tag, false, "unexpected output view tag after setting");
+
+ block blk_1;
+ generator.construct_block_manually(blk_1, blk_0, miner_account,
+ test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_miner_tx,
+ HF_VERSION_VIEW_TAGS, HF_VERSION_VIEW_TAGS, 0, crypto::hash(), 0, miner_tx);
+ events.push_back(blk_1);
+
+ DO_CALLBACK(events, "check_block_accepted");
+
+ return true;
+}
diff --git a/tests/core_tests/block_validation.h b/tests/core_tests/block_validation.h
index 2535039fb..3a157aaa9 100644
--- a/tests/core_tests/block_validation.h
+++ b/tests/core_tests/block_validation.h
@@ -230,3 +230,37 @@ struct get_test_options<gen_block_low_coinbase> {
hard_forks, 0
};
};
+
+struct gen_block_miner_tx_out_has_no_view_tag_before_hf_view_tags : public gen_block_accepted_base<2>
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+
+struct gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags : public gen_block_verification_base<1>
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<>
+struct get_test_options<gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags> {
+ const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(HF_VERSION_VIEW_TAGS+1, 1), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
+struct gen_block_miner_tx_out_has_view_tag_before_hf_view_tags : public gen_block_verification_base<1>
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+
+struct gen_block_miner_tx_out_has_view_tag_from_hf_view_tags : public gen_block_accepted_base<2>
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<>
+struct get_test_options<gen_block_miner_tx_out_has_view_tag_from_hf_view_tags> {
+ const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(HF_VERSION_VIEW_TAGS, 1), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp
index 689b6801b..61195c7b0 100644
--- a/tests/core_tests/chaingen.cpp
+++ b/tests/core_tests/chaingen.cpp
@@ -462,7 +462,9 @@ bool init_output_indices(map_output_idx_t& outs, std::map<uint64_t, std::vector<
size_t tx_global_idx = outs[out.amount].size() - 1;
outs[out.amount][tx_global_idx].idx = tx_global_idx;
// Is out to me?
- if (is_out_to_acc(from.get_keys(), boost::get<txout_to_key>(out.target), get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), j)) {
+ crypto::public_key output_public_key;
+ cryptonote::get_output_public_key(out, output_public_key);
+ if (is_out_to_acc(from.get_keys(), output_public_key, get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), j)) {
outs_mine[out.amount].push_back(tx_global_idx);
}
}
@@ -972,7 +974,7 @@ std::vector<cryptonote::tx_destination_entry> build_dsts(std::initializer_list<d
bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins,
const account_public_address& miner_address, transaction& tx, uint64_t fee,
- keypair* p_txkey/* = 0*/)
+ uint8_t hf_version/* = 1*/, keypair* p_txkey/* = 0*/)
{
keypair txkey;
txkey = keypair::generate(hw::get_device("default"));
@@ -987,7 +989,7 @@ bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins
// This will work, until size of constructed block is less then CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE
uint64_t block_reward;
- if (!get_block_reward(0, 0, already_generated_coins, block_reward, 1))
+ if (!get_block_reward(0, 0, already_generated_coins, block_reward, hf_version))
{
LOG_PRINT_L0("Block is too big");
return false;
@@ -999,12 +1001,20 @@ bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins
crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
crypto::derive_public_key(derivation, 0, miner_address.m_spend_public_key, out_eph_public_key);
+ bool use_view_tags = hf_version >= HF_VERSION_VIEW_TAGS;
+ crypto::view_tag view_tag;
+ if (use_view_tags)
+ crypto::derive_view_tag(derivation, 0, view_tag);
+
tx_out out;
- out.amount = block_reward;
- out.target = txout_to_key(out_eph_public_key);
+ cryptonote::set_tx_out(block_reward, out_eph_public_key, use_view_tags, view_tag, out);
+
tx.vout.push_back(out);
- tx.version = 1;
+ if (hf_version >= HF_VERSION_DYNAMIC_FEE)
+ tx.version = 2;
+ else
+ tx.version = 1;
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
return true;
diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h
index c1e592b86..5c8c9f79f 100644
--- a/tests/core_tests/chaingen.h
+++ b/tests/core_tests/chaingen.h
@@ -423,7 +423,8 @@ uint64_t sum_amount(const std::vector<cryptonote::tx_source_entry>& sources);
bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins,
const cryptonote::account_public_address& miner_address, cryptonote::transaction& tx,
- uint64_t fee, cryptonote::keypair* p_txkey = nullptr);
+ uint64_t fee, uint8_t hf_version = 1,
+ cryptonote::keypair* p_txkey = nullptr);
bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote::transaction& tx,
const cryptonote::block& blk_head, const cryptonote::account_base& from, const var_addr_t& to, uint64_t amount,
@@ -967,12 +968,14 @@ inline bool do_replay_file(const std::string& filename)
std::list<cryptonote::transaction> SET_NAME; \
MAKE_TX_MIX_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD);
-#define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, KEY) \
+#define MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(TX, BLK, HF_VERSION, KEY) \
transaction TX; \
if (!construct_miner_tx_manually(get_block_height(BLK) + 1, generator.get_already_generated_coins(BLK), \
- miner_account.get_keys().m_account_address, TX, 0, KEY)) \
+ miner_account.get_keys().m_account_address, TX, 0, HF_VERSION, KEY)) \
return false;
+#define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, KEY) MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(TX, BLK, 1, KEY)
+
#define MAKE_MINER_TX_MANUALLY(TX, BLK) MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, 0)
#define SET_EVENT_VISITOR_SETT(VEC_EVENTS, SETT) VEC_EVENTS.push_back(event_visitor_settings(SETT));
diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp
index 2e2d170ff..b89dff445 100644
--- a/tests/core_tests/chaingen_main.cpp
+++ b/tests/core_tests/chaingen_main.cpp
@@ -133,6 +133,10 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_block_miner_tx_out_is_big);
GENERATE_AND_PLAY(gen_block_miner_tx_has_no_out);
GENERATE_AND_PLAY(gen_block_miner_tx_has_out_to_alice);
+ GENERATE_AND_PLAY(gen_block_miner_tx_out_has_no_view_tag_before_hf_view_tags);
+ GENERATE_AND_PLAY(gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags);
+ GENERATE_AND_PLAY(gen_block_miner_tx_out_has_view_tag_before_hf_view_tags);
+ GENERATE_AND_PLAY(gen_block_miner_tx_out_has_view_tag_from_hf_view_tags);
GENERATE_AND_PLAY(gen_block_has_invalid_tx);
GENERATE_AND_PLAY(gen_block_is_too_big);
GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10
@@ -219,6 +223,15 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_increase_vin_and_fee);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_altered_extra);
GENERATE_AND_PLAY(gen_rct_tx_rct_altered_extra);
+ GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags);
+ // TODO: base test needs to be restructured to handle pre rct outputs after HF v12
+ // GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags);
+ GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags);
+ // GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags);
+ GENERATE_AND_PLAY(gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags);
+ GENERATE_AND_PLAY(gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags);
+ GENERATE_AND_PLAY(gen_rct_tx_rct_has_view_tag_before_hf_view_tags);
+ GENERATE_AND_PLAY(gen_rct_tx_rct_has_view_tag_from_hf_view_tags);
GENERATE_AND_PLAY(gen_rct_tx_uses_output_too_early);
GENERATE_AND_PLAY(gen_multisig_tx_valid_22_1_2);
diff --git a/tests/core_tests/rct.cpp b/tests/core_tests/rct.cpp
index 3a26de4c2..0926483fe 100644
--- a/tests/core_tests/rct.cpp
+++ b/tests/core_tests/rct.cpp
@@ -41,7 +41,7 @@ using namespace cryptonote;
// Tests
bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry>& events,
- const int *out_idx, int mixin, uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool valid,
+ const int *out_idx, int mixin, uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool use_view_tags, bool valid,
const std::function<void(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations)> &pre_tx,
const std::function<void(transaction &tx)> &post_tx) const
{
@@ -98,7 +98,9 @@ bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry
const size_t index_in_tx = 5;
src.amount = 30000000000000;
for (int m = 0; m < 4; ++m) {
- src.push_output(m, boost::get<txout_to_key>(blocks[m].miner_tx.vout[index_in_tx].target).key, src.amount);
+ crypto::public_key output_public_key;
+ cryptonote::get_output_public_key(blocks[m].miner_tx.vout[index_in_tx], output_public_key);
+ src.push_output(m, output_public_key, src.amount);
}
src.real_out_tx_key = cryptonote::get_tx_pub_key_from_extra(blocks[n].miner_tx);
src.real_output = n;
@@ -139,10 +141,13 @@ bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry
rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default"));
}
+ uint64_t fee = 0;
+ get_tx_fee(rct_txes[n], fee);
+
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes[n], blk_last, miner_account,
- test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs,
+ test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs | test_generator::bf_tx_fees,
4, 4, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
- crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 4),
+ crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 4, fee),
false, "Failed to generate block");
events.push_back(blk_txes[n]);
blk_last = blk_txes[n];
@@ -224,7 +229,7 @@ bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry
std::vector<crypto::secret_key> additional_tx_keys;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[miner_accounts[0].get_keys().m_account_address.m_spend_public_key] = {0,0};
- bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_keys, true, rct_config);
+ bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_keys, true, rct_config, NULL, use_view_tags);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
if (post_tx)
@@ -244,7 +249,8 @@ bool gen_rct_tx_validation_base::generate_with(std::vector<test_event_entry>& ev
const std::function<void(transaction &tx)> &post_tx) const
{
const rct::RCTConfig rct_config { rct::RangeProofBorromean, 0 };
- return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 4, rct_config, valid, pre_tx, post_tx);
+ bool use_view_tags = false;
+ return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 4, rct_config, use_view_tags, valid, pre_tx, post_tx);
}
bool gen_rct_tx_valid_from_pre_rct::generate(std::vector<test_event_entry>& events) const
@@ -517,11 +523,99 @@ bool gen_rct_tx_rct_altered_extra::generate(std::vector<test_event_entry>& event
NULL, [&failed](transaction &tx) {std::string extra_nonce; crypto::hash pid = crypto::null_hash; set_payment_id_to_tx_extra_nonce(extra_nonce, pid); if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) failed = true; }) && !failed;
}
+bool gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 2;
+ const int out_idx[] = {0, -1};
+ const uint64_t amount_paid = 10000;
+ bool use_view_tags = false;
+ bool valid = true;
+ return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, {}, use_view_tags, valid, NULL, NULL);
+}
+
+bool gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 10;
+ const int out_idx[] = {0, -1};
+ const uint64_t amount_paid = 10000;
+ const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 };
+ bool use_view_tags = false;
+ bool valid = false;
+ return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS, rct_config, use_view_tags, valid, NULL, NULL);
+}
+
+bool gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 2;
+ const int out_idx[] = {0, -1};
+ const uint64_t amount_paid = 10000;
+ bool use_view_tags = true;
+ bool valid = false;
+ return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, {}, use_view_tags, valid, NULL, NULL);
+}
+
+bool gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 10;
+ const int out_idx[] = {0, -1};
+ const uint64_t amount_paid = 10000;
+ const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 };
+ bool use_view_tags = true;
+ bool valid = true;
+ return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS, rct_config, use_view_tags, valid, NULL, NULL);
+}
+
+bool gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 2;
+ const int out_idx[] = {1, -1};
+ const uint64_t amount_paid = 10000;
+ const rct::RCTConfig rct_config { rct::RangeProofBorromean, 0 };
+ bool use_view_tags = false;
+ bool valid = true;
+ return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, rct_config, use_view_tags, valid, NULL, NULL);
+}
+
+bool gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 10;
+ const int out_idx[] = {1, -1};
+ const uint64_t amount_paid = 10000;
+ const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 };
+ bool use_view_tags = false;
+ bool valid = false;
+ return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS+1, rct_config, use_view_tags, valid, NULL, NULL);
+}
+
+bool gen_rct_tx_rct_has_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 2;
+ const int out_idx[] = {1, -1};
+ const uint64_t amount_paid = 10000;
+ const rct::RCTConfig rct_config { rct::RangeProofBorromean, 0 };
+ bool use_view_tags = true;
+ bool valid = false;
+ return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, rct_config, use_view_tags, valid, NULL, NULL);
+}
+
+bool gen_rct_tx_rct_has_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const
+{
+ const int mixin = 10;
+ const int out_idx[] = {1, -1};
+ const uint64_t amount_paid = 10000;
+ const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 };
+ bool use_view_tags = true;
+ bool valid = true;
+ return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS, rct_config, use_view_tags, valid, NULL, NULL);
+}
+
bool gen_rct_tx_uses_output_too_early::generate(std::vector<test_event_entry>& events) const
{
const int mixin = 10;
const int out_idx[] = {1, -1};
const uint64_t amount_paid = 10000;
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 2 };
- return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE-3, HF_VERSION_ENFORCE_MIN_AGE, rct_config, false, NULL, NULL);
+ bool use_view_tags = false;
+ bool valid = false;
+ return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE-3, HF_VERSION_ENFORCE_MIN_AGE, rct_config, use_view_tags, valid, NULL, NULL);
}
diff --git a/tests/core_tests/rct.h b/tests/core_tests/rct.h
index dee074e4c..c20e8a580 100644
--- a/tests/core_tests/rct.h
+++ b/tests/core_tests/rct.h
@@ -70,7 +70,7 @@ struct gen_rct_tx_validation_base : public test_chain_unit_base
}
bool generate_with_full(std::vector<test_event_entry>& events, const int *out_idx, int mixin,
- uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool valid,
+ uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool use_view_tags, bool valid,
const std::function<void(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations)> &pre_tx,
const std::function<void(cryptonote::transaction &tx)> &post_tx) const;
bool generate_with(std::vector<test_event_entry>& events, const int *out_idx, int mixin,
@@ -266,6 +266,74 @@ struct gen_rct_tx_rct_altered_extra : public gen_rct_tx_validation_base
};
template<> struct get_test_options<gen_rct_tx_rct_altered_extra>: public get_test_options<gen_rct_tx_validation_base> {};
+struct gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {};
+
+struct gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags> {
+ const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS, 69), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
+struct gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {};
+
+struct gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags> {
+ const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS, 69), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
+struct gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {};
+
+struct gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags> {
+ const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS+1, 69), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
+struct gen_rct_tx_rct_has_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_rct_has_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {};
+
+struct gen_rct_tx_rct_has_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct_tx_rct_has_view_tag_from_hf_view_tags> {
+ const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS, 69), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
struct gen_rct_tx_uses_output_too_early : public gen_rct_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
diff --git a/tests/crypto/main.cpp b/tests/crypto/main.cpp
index 59a2a7d77..045ffc08d 100644
--- a/tests/crypto/main.cpp
+++ b/tests/crypto/main.cpp
@@ -260,7 +260,6 @@ int main(int argc, char *argv[]) {
goto error;
}
} else if (cmd == "check_ge_p3_identity") {
- cerr << "Testing: " << cmd << endl;
public_key point;
bool expected_bad, expected_good, result_badfunc, result_goodfunc;
get(input, point, expected_bad, expected_good);
@@ -269,6 +268,15 @@ int main(int argc, char *argv[]) {
if (expected_bad != result_badfunc || expected_good != result_goodfunc) {
goto error;
}
+ } else if (cmd == "derive_view_tag") {
+ key_derivation derivation;
+ size_t output_index;
+ view_tag expected, actual;
+ get(input, derivation, output_index, expected);
+ derive_view_tag(derivation, output_index, actual);
+ if (expected != actual) {
+ goto error;
+ }
} else {
throw ios_base::failure("Unknown function: " + cmd);
}
diff --git a/tests/crypto/tests.txt b/tests/crypto/tests.txt
index 3a7fe5453..d387aa09d 100644
--- a/tests/crypto/tests.txt
+++ b/tests/crypto/tests.txt
@@ -5473,3 +5473,59 @@ check_ge_p3_identity 046e1450f147f3ade34d149973913cc75d4e7b9669eb1ed61da0f1d4a0b
check_ge_p3_identity ca8a2f621cfc7aa3efcd7ddf55dce5352e757b38aca0869b050c0a27824e5c5e true true
check_ge_p3_identity 64a247eef6087d86e1e9fa048a3c181fdb1728431f29ba738634bdc38f02a859 true true
check_ge_p3_identity cff0c7170a41395b0658ee42b76545c45360736b973ab2f31f6f227b9415df67 true true
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 0 76
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 1 d6
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 2 87
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 3 1b
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 12 d6
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 13 e9
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 14 12
+derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 15 26
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 0 70
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 1 81
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 2 a0
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 3 ec
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 12 22
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 13 0a
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 14 87
+derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 15 76
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 0 93
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 1 67
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 2 9d
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 3 2d
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 12 63
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 13 cf
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 14 ef
+derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 15 10
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 0 90
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 1 5a
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 2 de
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 3 21
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 12 57
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 13 52
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 14 6f
+derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 15 eb
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 0 c6
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 1 60
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 2 f0
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 3 71
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 12 0e
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 13 42
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 14 b2
+derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 15 61
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 0 4c
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 1 9b
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 2 64
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 3 ff
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 12 e3
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 13 24
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 14 ea
+derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 15 3b
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 0 74
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 1 77
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 2 a9
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 3 44
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 12 75
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 13 05
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 14 ca
+derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 15 00
diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt
index 03b124981..c079afe3a 100644
--- a/tests/performance_tests/CMakeLists.txt
+++ b/tests/performance_tests/CMakeLists.txt
@@ -43,6 +43,7 @@ set(performance_tests_headers
generate_keypair.h
signature.h
is_out_to_acc.h
+ out_can_be_to_acc.h
subaddress_expand.h
range_proof.h
bulletproof.h
diff --git a/tests/performance_tests/derive_view_tag.h b/tests/performance_tests/derive_view_tag.h
new file mode 100644
index 000000000..ee4efb16d
--- /dev/null
+++ b/tests/performance_tests/derive_view_tag.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2014-2021, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include "crypto/crypto.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+
+#include "single_tx_test_base.h"
+
+class test_derive_view_tag : public single_tx_test_base
+{
+public:
+ static const size_t loop_count = 10000;
+
+ bool init()
+ {
+ if (!single_tx_test_base::init())
+ return false;
+
+ crypto::generate_key_derivation(m_tx_pub_key, m_bob.get_keys().m_view_secret_key, m_key_derivation);
+
+ return true;
+ }
+
+ bool test()
+ {
+ crypto::view_tag view_tag;
+ crypto::derive_view_tag(m_key_derivation, 0, view_tag);
+ return true;
+ }
+
+private:
+ crypto::key_derivation m_key_derivation;
+};
diff --git a/tests/performance_tests/is_out_to_acc.h b/tests/performance_tests/is_out_to_acc.h
index d1204ee68..75d4a5c46 100644
--- a/tests/performance_tests/is_out_to_acc.h
+++ b/tests/performance_tests/is_out_to_acc.h
@@ -43,8 +43,9 @@ public:
bool test()
{
- const cryptonote::txout_to_key& tx_out = boost::get<cryptonote::txout_to_key>(m_tx.vout[0].target);
- return cryptonote::is_out_to_acc(m_bob.get_keys(), tx_out, m_tx_pub_key, m_additional_tx_pub_keys, 0);
+ crypto::public_key output_public_key;
+ cryptonote::get_output_public_key(m_tx.vout[0], output_public_key);
+ return cryptonote::is_out_to_acc(m_bob.get_keys(), output_public_key, m_tx_pub_key, m_additional_tx_pub_keys, 0);
}
};
diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp
index 8bd1008cb..71c736977 100644
--- a/tests/performance_tests/main.cpp
+++ b/tests/performance_tests/main.cpp
@@ -42,6 +42,7 @@
#include "cn_slow_hash.h"
#include "derive_public_key.h"
#include "derive_secret_key.h"
+#include "derive_view_tag.h"
#include "ge_frombytes_vartime.h"
#include "ge_tobytes.h"
#include "generate_key_derivation.h"
@@ -50,6 +51,7 @@
#include "generate_keypair.h"
#include "signature.h"
#include "is_out_to_acc.h"
+#include "out_can_be_to_acc.h"
#include "subaddress_expand.h"
#include "sc_reduce32.h"
#include "sc_check.h"
@@ -194,6 +196,9 @@ int main(int argc, char** argv)
TEST_PERFORMANCE0(filter, p, test_is_out_to_acc);
TEST_PERFORMANCE0(filter, p, test_is_out_to_acc_precomp);
+ TEST_PERFORMANCE2(filter, p, test_out_can_be_to_acc, false, true); // no view tag, owned
+ TEST_PERFORMANCE2(filter, p, test_out_can_be_to_acc, true, false); // use view tag, not owned
+ TEST_PERFORMANCE2(filter, p, test_out_can_be_to_acc, true, true); // use view tag, owned
TEST_PERFORMANCE0(filter, p, test_generate_key_image_helper);
TEST_PERFORMANCE0(filter, p, test_generate_key_derivation);
TEST_PERFORMANCE0(filter, p, test_generate_key_image);
@@ -206,6 +211,7 @@ int main(int argc, char** argv)
TEST_PERFORMANCE0(filter, p, test_sc_check);
TEST_PERFORMANCE1(filter, p, test_signature, false);
TEST_PERFORMANCE1(filter, p, test_signature, true);
+ TEST_PERFORMANCE0(filter, p, test_derive_view_tag);
TEST_PERFORMANCE2(filter, p, test_wallet2_expand_subaddresses, 50, 200);
diff --git a/tests/performance_tests/out_can_be_to_acc.h b/tests/performance_tests/out_can_be_to_acc.h
new file mode 100644
index 000000000..86e236b7b
--- /dev/null
+++ b/tests/performance_tests/out_can_be_to_acc.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2014-2021, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include "crypto/crypto.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+
+#include "single_tx_test_base.h"
+
+using namespace crypto;
+
+// use_view_tags: whether to enable view tag checking
+// is_owned: whether the output is owned by us
+template<bool use_view_tags, bool is_owned>
+class test_out_can_be_to_acc : public single_tx_test_base
+{
+ public:
+ static const size_t loop_count = 1000;
+
+ bool init()
+ {
+ if (!single_tx_test_base::init())
+ return false;
+
+ crypto::key_derivation key_derivation;
+ crypto::view_tag vt;
+
+ m_output_index = 0;
+ m_view_secret_key = m_bob.get_keys().m_view_secret_key;
+ m_spend_public_key = m_bob.get_keys().m_account_address.m_spend_public_key;
+
+ cryptonote::get_output_public_key(m_tx.vout[m_output_index], m_output_public_key);
+
+ if (use_view_tags)
+ {
+ crypto::generate_key_derivation(m_tx_pub_key, m_view_secret_key, key_derivation);
+ crypto::derive_view_tag(key_derivation, m_output_index, vt);
+ m_view_tag_opt = vt;
+ }
+ else
+ m_view_tag_opt = boost::optional<crypto::view_tag>();
+
+ return true;
+ }
+
+ bool test()
+ {
+ // include key derivation to demonstrate performance improvement when using view tags
+ crypto::key_derivation key_derivation;
+ crypto::generate_key_derivation(m_tx_pub_key, m_view_secret_key, key_derivation);
+
+ // if using view tags, this ensures we computed the view tag properly
+ if (!cryptonote::out_can_be_to_acc(m_view_tag_opt, key_derivation, m_output_index))
+ return false;
+
+ // if user owns output, this tests the output public key matches the derived
+ if (is_owned)
+ {
+ crypto::public_key output_public_key;
+ crypto::derive_public_key(key_derivation, m_output_index, m_spend_public_key, output_public_key);
+
+ if (m_output_public_key != output_public_key)
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ size_t m_output_index;
+ crypto::secret_key m_view_secret_key;
+ crypto::public_key m_spend_public_key;
+ crypto::public_key m_output_public_key;
+ boost::optional<crypto::view_tag> m_view_tag_opt;
+};