diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 65ec6fd7c9..808a6fdc21 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1964,6 +1964,25 @@ void wallet2::set_subaddress_lookahead(size_t major, size_t minor) THROW_WALLET_EXCEPTION_IF(major > 0xffffffff, error::wallet_internal_error, "Subaddress major lookahead is too large"); THROW_WALLET_EXCEPTION_IF(minor == 0, error::wallet_internal_error, "Subaddress minor lookahead may not be zero"); THROW_WALLET_EXCEPTION_IF(minor > 0xffffffff, error::wallet_internal_error, "Subaddress minor lookahead is too large"); + + if (major > m_subaddress_lookahead_major) { // if increasing the lookahead + // then generate new subaddress pubkeys and add them to m_subaddresses table + for (uint32_t i = m_subaddress_labels.size()+m_subaddress_lookahead_major; i < m_subaddress_labels.size()+major; i++) { // m_subaddress_labels are the accounts the user is conciously keeping track of. We want that number plus the lookahead major accounts in our key table + for (uint32_t j = 0; j < minor; j++) { // these are newly made accounts, minor index will start from zero + cryptonote::subaddress_index idx = {i,j}; + create_one_off_subaddress(idx); // then generate the key and add it to the table + } + } + } + if (minor > m_subaddress_lookahead_minor) { // if increasing the minor lookahead we need to also go back and expand the existing accounts + for (uint32_t i = 0; i < m_subaddress_labels.size()+m_subaddress_lookahead_major; i++) { + uint32_t minor_idx_start = i < m_subaddress_labels.size() ? m_subaddress_labels[i].size()+m_subaddress_lookahead_minor : m_subaddress_lookahead_minor; // if there are existing minor indices being tracked under this account we need to account for that + for (uint32_t j = minor_idx_start; j < minor; j++) { + cryptonote::subaddress_index idx = {i,j}; + create_one_off_subaddress(idx); + } + } + } m_subaddress_lookahead_major = major; m_subaddress_lookahead_minor = minor; } diff --git a/tests/unit_tests/subaddress.cpp b/tests/unit_tests/subaddress.cpp index 17fc0fe785..b03e58f5a0 100644 --- a/tests/unit_tests/subaddress.cpp +++ b/tests/unit_tests/subaddress.cpp @@ -28,6 +28,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include +#include #include "gtest/gtest.h" #include "include_base_utils.h" @@ -101,3 +102,29 @@ TEST_F(WalletSubaddress, OutOfBoundsIndexes) EXPECT_STREQ("index.minor is out of bound", e.what()); } } + +TEST_F(WalletSubaddress, ExpandPubkeyTable) +{ + // these test assume we are starting with the default setup state + EXPECT_EQ(2, w1.get_num_subaddress_accounts()); + EXPECT_EQ(50, w1.get_subaddress_lookahead().first); + EXPECT_EQ(200, w1.get_subaddress_lookahead().second); + // get_subaddress_index looks up keys in the private m_subaddresses dictionary so we will use it to test if a key is properly being scanned for + cryptonote::subaddress_index test_idx = {50, 199}; + auto subaddr = w1.get_subaddress(test_idx); + EXPECT_NE(boost::none, w1.get_subaddress_index(subaddr)); + // fist test expanding the major lookahead + w1.set_subaddress_lookahead(100, 200); + EXPECT_EQ(100, w1.get_subaddress_lookahead().first); + EXPECT_EQ(200, w1.get_subaddress_lookahead().second); + test_idx = {100, 199}; + subaddr = w1.get_subaddress(test_idx); + EXPECT_NE(boost::none, w1.get_subaddress_index(subaddr)); + // next test expanding the minor lookahead + w1.set_subaddress_lookahead(100, 300); + EXPECT_EQ(100, w1.get_subaddress_lookahead().first); + EXPECT_EQ(300, w1.get_subaddress_lookahead().second); + test_idx = {100, 299}; + subaddr = w1.get_subaddress(test_idx); + EXPECT_NE(boost::none, w1.get_subaddress_index(subaddr)); +}