From 0741363499714153ab73d6fa12e6868ca00658fb Mon Sep 17 00:00:00 2001 From: moneroexamples Date: Sun, 5 May 2019 08:40:04 +0800 Subject: [PATCH] test RegularTwoOutputTxToSubaddress added --- src/Account.h | 13 +++++++ src/UniversalIdentifier.cpp | 53 ++++++++++++++++++++++------- src/UniversalIdentifier.hpp | 16 ++++++--- tests/account_tests.cpp | 1 + tests/universalidentifier_tests.cpp | 9 +++++ 5 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/Account.h b/src/Account.h index f6c38a3..78ec93e 100644 --- a/src/Account.h +++ b/src/Account.h @@ -375,7 +375,20 @@ Account::ai_to_str(address_parse_info const& addr_info, inline std::ostream& operator<<(std::ostream& os, Account const& _acc) { + + string subaddr_str {"n/a"}; + + if (_acc.subaddr_idx) + { + stringstream ss; + + ss << *_acc.subaddr_idx; + + subaddr_str = ss.str(); + } + return os << "nt:" << static_cast(_acc.nettype) + << "," << subaddr_str << ",a:" << _acc.ai2str() << ",v:" << _acc.vk2str() << ",s:" << _acc.sk2str(); diff --git a/src/UniversalIdentifier.cpp b/src/UniversalIdentifier.cpp index fd87284..5c6f32f 100644 --- a/src/UniversalIdentifier.cpp +++ b/src/UniversalIdentifier.cpp @@ -104,6 +104,18 @@ Output::identify(transaction const& tx, auto const& pub_spend_key = get_address()->address.m_spend_public_key; + // if we have PrimaryAccount we can check + // if a given output belongs to any of its + // its subaddresses + PrimaryAccount* pacc {nullptr}; + + if (acc && !acc->is_subaddress()) + { + // so we have primary address + pacc = static_cast(acc); + } + + for (auto i = 0u; i < tx.vout.size(); ++i) { // i will act as output indxes in the tx @@ -124,8 +136,16 @@ Output::identify(transaction const& tx, // public monero address. Primary address is // a special case of subaddress. + // we are always going to have the subaddress_spend + // key if an output is ours crypto::public_key subaddress_spendkey; + // however we might not have its index, in case + // we are not using primary addresses directly + // but instead use a subaddress for searching + // outputs + std::unique_ptr subaddr_idx; + hwdev.derive_subaddress_public_key( txout_key.key, derivation, i, subaddress_spendkey); @@ -138,9 +158,9 @@ Output::identify(transaction const& tx, bool mine_output {false}; - if (!acc) + if (!pacc) { - // if acc is not given, we check generated + // if pacc is not given, we check generated // subaddress_spendkey against the spendkey // of the address for which the Output identifier // was instantiated @@ -148,17 +168,14 @@ Output::identify(transaction const& tx, } else { - // if acc is given, we are going to use its + // if pacc is given, we are going to use its // subaddress unordered map to check if generated // subaddress_spendkey is one of its keys. this is // because the map can contain spendkeys of subaddreses // assiciated with primary address. primary address's // spendkey will be one of the keys as a special case - assert(!acc->is_subaddress()); - auto sacc = static_cast(acc); - - auto subaddr_idx = sacc->has_subaddress(subaddress_spendkey); + subaddr_idx = pacc->has_subaddress(subaddress_spendkey); mine_output = bool {subaddr_idx}; } @@ -168,14 +185,20 @@ Output::identify(transaction const& tx, if (!mine_output && !additional_tx_pub_keys.empty()) { // check for output using additional tx public keys - crypto::public_key subaddress_spendkey; - hwdev.derive_subaddress_public_key( txout_key.key, additional_derivations[i], i, subaddress_spendkey); - mine_output = (pub_spend_key == subaddress_spendkey); + if (!pacc) + { + mine_output = (pub_spend_key == subaddress_spendkey); + } + else + { + subaddr_idx = pacc->has_subaddress(subaddress_spendkey); + mine_output = bool {subaddr_idx}; + } with_additional = true; } @@ -246,11 +269,17 @@ Output::identify(transaction const& tx, info{ txout_key.key, amount, i, derivation_to_save, - rtc_outpk, rtc_mask, rtc_amount + rtc_outpk, rtc_mask, rtc_amount, + subaddress_spendkey }); - total_xmr += amount; + if (subaddr_idx) + { + auto& out = identified_outputs.back(); + out.subaddr_idx = *subaddr_idx; + } + total_xmr += amount; } // if (mine_output) } // for (uint64_t i = 0; i < tx.vout.size(); ++i) diff --git a/src/UniversalIdentifier.hpp b/src/UniversalIdentifier.hpp index 60d1443..6bc7776 100644 --- a/src/UniversalIdentifier.hpp +++ b/src/UniversalIdentifier.hpp @@ -70,11 +70,6 @@ class Output : public BaseIdentifier { public: - //Output(address_parse_info const* _address, - //secret_key const* _viewkey) - //: BaseIdentifier(_address, _viewkey) - //{} - using BaseIdentifier::BaseIdentifier; void identify(transaction const& tx, @@ -105,6 +100,17 @@ public: rct::key rtc_mask; rct::key rtc_amount; + public_key subaddress_spendkey; + subaddress_index subaddr_idx { + UINT32_MAX, UINT32_MAX}; + // the max value means not given + + bool has_subaddress_index() const + { + return subaddr_idx.major != UINT32_MAX + && subaddr_idx.minor != UINT32_MAX; + } + friend std::ostream& operator<<(std::ostream& os, info const& _info); }; diff --git a/tests/account_tests.cpp b/tests/account_tests.cpp index cc480b4..fddc06c 100644 --- a/tests/account_tests.cpp +++ b/tests/account_tests.cpp @@ -362,6 +362,7 @@ TEST(SUBADDRESS, PupulateSubaddresses) { auto sacc = pacc->gen_subaddress(kv.second); if (!sacc) continue; + cout << *sacc << endl; EXPECT_EQ(kv.first, sacc->psk()); } } diff --git a/tests/universalidentifier_tests.cpp b/tests/universalidentifier_tests.cpp index 30fea29..1e966e0 100644 --- a/tests/universalidentifier_tests.cpp +++ b/tests/universalidentifier_tests.cpp @@ -425,6 +425,15 @@ TEST(Subaddresses, RegularTwoOutputTxToSubaddress) EXPECT_TRUE(identifier.get<0>()->get() == jtx->recipients.at(0).outputs); + + auto const& output_info + = identifier.get<0>()->get().at(0); + + EXPECT_TRUE(output_info.has_subaddress_index()); + + subaddress_index expected_idx {0, 6}; + + EXPECT_EQ(output_info.subaddr_idx, expected_idx); }