diff options
author | j-berman <justinberman@protonmail.com> | 2021-11-15 05:23:53 -0800 |
---|---|---|
committer | j-berman <justinberman@protonmail.com> | 2022-04-18 00:49:53 -0700 |
commit | ea87b30f8907ee11252433811e7a7d0c46758cca (patch) | |
tree | 61dedf56a781a83285be092b078019bebdc94f2e /tests/core_tests/block_validation.cpp | |
parent | Merge pull request #8207 (diff) | |
download | monero-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/core_tests/block_validation.cpp')
-rw-r--r-- | tests/core_tests/block_validation.cpp | 124 |
1 files changed, 124 insertions, 0 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; +} |