From a57a1d42d52fe51e5b413a1fd3a5ef2b7a2120e3 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 1 Sep 2019 22:10:51 +0200 Subject: [PATCH] test: add unit test for wallet watch-only methods involving PubKeys The motivation for this addition was to unit test the function wallet.cpp:ExtractPubKey() (see recent change in commit 798a589aff64b83a0844688a661f4bd987c3340c) which is however static and only indirectly available via the public methods AddWatchOnly(), LoadWatchOnly() and RemoveWatchOnly(). Since the first of those methods also stores the addresses to the disk, the second, simpler one was chosen which only operates in memory. test: add missing wallet lock for test case WatchOnlyPubKeys test: test case WatchOnlyPubKeys, suggested review changes by instagibbs test: test case WatchOnlyPubKeys, suggested review changes by achow101 test: test case WatchOnlyPubKeys, s/isPubKeyFullyValid/is_pubkey_fully_valid --- src/wallet/test/wallet_tests.cpp | 78 ++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 8af05dea458..66601fd9b72 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -334,6 +334,84 @@ BOOST_AUTO_TEST_CASE(LoadReceiveRequests) BOOST_CHECK_EQUAL(values[1], "val_rr1"); } +// Test some watch-only wallet methods by the procedure of loading (LoadWatchOnly), +// checking (HaveWatchOnly), getting (GetWatchPubKey) and removing (RemoveWatchOnly) a +// given PubKey, resp. its corresponding P2PK Script. Results of the the impact on +// the address -> PubKey map is dependent on whether the PubKey is a point on the curve +static void TestWatchOnlyPubKey(CWallet& wallet, const CPubKey& add_pubkey) +{ + CScript p2pk = GetScriptForRawPubKey(add_pubkey); + CKeyID add_address = add_pubkey.GetID(); + CPubKey found_pubkey; + LOCK(wallet.cs_wallet); + + // all Scripts (i.e. also all PubKeys) are added to the general watch-only set + BOOST_CHECK(!wallet.HaveWatchOnly(p2pk)); + wallet.LoadWatchOnly(p2pk); + BOOST_CHECK(wallet.HaveWatchOnly(p2pk)); + + // only PubKeys on the curve shall be added to the watch-only address -> PubKey map + bool is_pubkey_fully_valid = add_pubkey.IsFullyValid(); + if (is_pubkey_fully_valid) { + BOOST_CHECK(wallet.GetWatchPubKey(add_address, found_pubkey)); + BOOST_CHECK(found_pubkey == add_pubkey); + } else { + BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey)); + BOOST_CHECK(found_pubkey == CPubKey()); // passed key is unchanged + } + + wallet.RemoveWatchOnly(p2pk); + BOOST_CHECK(!wallet.HaveWatchOnly(p2pk)); + + if (is_pubkey_fully_valid) { + BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey)); + BOOST_CHECK(found_pubkey == add_pubkey); // passed key is unchanged + } +} + +// Cryptographically invalidate a PubKey whilst keeping length and first byte +static void PollutePubKey(CPubKey& pubkey) +{ + std::vector pubkey_raw(pubkey.begin(), pubkey.end()); + std::fill(pubkey_raw.begin()+1, pubkey_raw.end(), 0); + pubkey = CPubKey(pubkey_raw); + assert(!pubkey.IsFullyValid()); + assert(pubkey.IsValid()); +} + +// Test watch-only wallet logic for PubKeys +BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys) +{ + CKey key; + CPubKey pubkey; + + BOOST_CHECK(!m_wallet.HaveWatchOnly()); + + // uncompressed valid PubKey + key.MakeNewKey(false); + pubkey = key.GetPubKey(); + assert(!pubkey.IsCompressed()); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // uncompressed cryptographically invalid PubKey + PollutePubKey(pubkey); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // compressed valid PubKey + key.MakeNewKey(true); + pubkey = key.GetPubKey(); + assert(pubkey.IsCompressed()); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // compressed cryptographically invalid PubKey + PollutePubKey(pubkey); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // invalid empty PubKey + pubkey = CPubKey(); + TestWatchOnlyPubKey(m_wallet, pubkey); +} + class ListCoinsTestingSetup : public TestChain100Setup { public: