Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/test/wallet_tests.cpp
Show All 22 Lines | |||||
#include <cstdint> | #include <cstdint> | ||||
#include <memory> | #include <memory> | ||||
#include <vector> | #include <vector> | ||||
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) | BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) | ||||
static void AddKey(CWallet &wallet, const CKey &key) { | static void AddKey(CWallet &wallet, const CKey &key) { | ||||
auto spk_man = wallet.GetLegacyScriptPubKeyMan(); | |||||
LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
wallet.AddKeyPubKey(key, key.GetPubKey()); | AssertLockHeld(spk_man->cs_wallet); | ||||
spk_man->AddKeyPubKey(key, key.GetPubKey()); | |||||
} | } | ||||
BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) { | BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) { | ||||
// Cap last block file size, and mine new block in a new block file. | // Cap last block file size, and mine new block in a new block file. | ||||
CBlockIndex *oldTip = ::ChainActive().Tip(); | CBlockIndex *oldTip = ::ChainActive().Tip(); | ||||
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE; | GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE; | ||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | ||||
CBlockIndex *newTip = ::ChainActive().Tip(); | CBlockIndex *newTip = ::ChainActive().Tip(); | ||||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { | ||||
std::string backup_file = (GetDataDir() / "wallet.backup").string(); | std::string backup_file = (GetDataDir() / "wallet.backup").string(); | ||||
// Import key into wallet and call dumpwallet to create backup file. | // Import key into wallet and call dumpwallet to create backup file. | ||||
{ | { | ||||
std::shared_ptr<CWallet> wallet = | std::shared_ptr<CWallet> wallet = | ||||
std::make_shared<CWallet>(Params(), chain.get(), WalletLocation(), | std::make_shared<CWallet>(Params(), chain.get(), WalletLocation(), | ||||
WalletDatabase::CreateDummy()); | WalletDatabase::CreateDummy()); | ||||
auto spk_man = wallet->GetLegacyScriptPubKeyMan(); | |||||
LOCK(wallet->cs_wallet); | LOCK(wallet->cs_wallet); | ||||
wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = | AssertLockHeld(spk_man->cs_wallet); | ||||
spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = | |||||
KEY_TIME; | KEY_TIME; | ||||
wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | ||||
JSONRPCRequest request; | JSONRPCRequest request; | ||||
request.params.setArray(); | request.params.setArray(); | ||||
request.params.push_back(backup_file); | request.params.push_back(backup_file); | ||||
AddWallet(wallet); | AddWallet(wallet); | ||||
::dumpwallet(GetConfig(), request); | ::dumpwallet(GetConfig(), request); | ||||
RemoveWallet(wallet); | RemoveWallet(wallet); | ||||
} | } | ||||
Show All 29 Lines | |||||
// This is a regression test written to verify a bugfix for the immature credit | // This is a regression test written to verify a bugfix for the immature credit | ||||
// function. Similar tests probably should be written for the other credit and | // function. Similar tests probably should be written for the other credit and | ||||
// debit functions. | // debit functions. | ||||
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup) { | BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup) { | ||||
NodeContext node; | NodeContext node; | ||||
auto chain = interfaces::MakeChain(node, Params()); | auto chain = interfaces::MakeChain(node, Params()); | ||||
CWallet wallet(Params(), chain.get(), WalletLocation(), | CWallet wallet(Params(), chain.get(), WalletLocation(), | ||||
WalletDatabase::CreateDummy()); | WalletDatabase::CreateDummy()); | ||||
auto spk_man = wallet.GetLegacyScriptPubKeyMan(); | |||||
CWalletTx wtx(&wallet, m_coinbase_txns.back()); | CWalletTx wtx(&wallet, m_coinbase_txns.back()); | ||||
auto locked_chain = chain->lock(); | auto locked_chain = chain->lock(); | ||||
LockAssertion lock(::cs_main); | LockAssertion lock(::cs_main); | ||||
LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
AssertLockHeld(spk_man->cs_wallet); | |||||
wtx.SetConf(CWalletTx::Status::CONFIRMED, | wtx.SetConf(CWalletTx::Status::CONFIRMED, | ||||
::ChainActive().Tip()->GetBlockHash(), 0); | ::ChainActive().Tip()->GetBlockHash(), 0); | ||||
// Call GetImmatureCredit() once before adding the key to the wallet to | // Call GetImmatureCredit() once before adding the key to the wallet to | ||||
// cache the current immature credit amount, which is 0. | // cache the current immature credit amount, which is 0. | ||||
BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), Amount::zero()); | BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), Amount::zero()); | ||||
// Invalidate the cached value, add the key, and make sure a new immature | // Invalidate the cached value, add the key, and make sure a new immature | ||||
// credit amount is calculated. | // credit amount is calculated. | ||||
wtx.MarkDirty(); | wtx.MarkDirty(); | ||||
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | BOOST_CHECK(spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey())); | ||||
BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 50 * COIN); | BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 50 * COIN); | ||||
} | } | ||||
static int64_t AddTx(CWallet &wallet, uint32_t lockTime, int64_t mockTime, | static int64_t AddTx(CWallet &wallet, uint32_t lockTime, int64_t mockTime, | ||||
int64_t blockTime) { | int64_t blockTime) { | ||||
CMutableTransaction tx; | CMutableTransaction tx; | ||||
tx.nLockTime = lockTime; | tx.nLockTime = lockTime; | ||||
SetMockTime(mockTime); | SetMockTime(mockTime); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(LoadReceiveRequests) { | ||||
m_wallet.AddDestData(dest, "rr1", "val_rr1"); | m_wallet.AddDestData(dest, "rr1", "val_rr1"); | ||||
auto values = m_wallet.GetDestValues("rr"); | auto values = m_wallet.GetDestValues("rr"); | ||||
BOOST_CHECK_EQUAL(values.size(), 2U); | BOOST_CHECK_EQUAL(values.size(), 2U); | ||||
BOOST_CHECK_EQUAL(values[0], "val_rr0"); | BOOST_CHECK_EQUAL(values[0], "val_rr0"); | ||||
BOOST_CHECK_EQUAL(values[1], "val_rr1"); | BOOST_CHECK_EQUAL(values[1], "val_rr1"); | ||||
} | } | ||||
// Test some watch-only wallet methods by the procedure of loading | // Test some watch-only LegacyScriptPubKeyMan methods by the procedure of | ||||
// (LoadWatchOnly), checking (HaveWatchOnly), getting (GetWatchPubKey) and | // loading (LoadWatchOnly), checking (HaveWatchOnly), getting (GetWatchPubKey) | ||||
// removing (RemoveWatchOnly) a given PubKey, resp. its corresponding P2PK | // and removing (RemoveWatchOnly) a given PubKey, resp. its corresponding P2PK | ||||
// Script. Results of the the impact on the address -> PubKey map is dependent | // Script. Results of the the impact on the address -> PubKey map is dependent | ||||
// on whether the PubKey is a point on the curve | // on whether the PubKey is a point on the curve | ||||
static void TestWatchOnlyPubKey(CWallet &wallet, const CPubKey &add_pubkey) { | static void TestWatchOnlyPubKey(LegacyScriptPubKeyMan *spk_man, | ||||
const CPubKey &add_pubkey) { | |||||
CScript p2pk = GetScriptForRawPubKey(add_pubkey); | CScript p2pk = GetScriptForRawPubKey(add_pubkey); | ||||
CKeyID add_address = add_pubkey.GetID(); | CKeyID add_address = add_pubkey.GetID(); | ||||
CPubKey found_pubkey; | CPubKey found_pubkey; | ||||
LOCK(wallet.cs_wallet); | LOCK(spk_man->cs_wallet); | ||||
// all Scripts (i.e. also all PubKeys) are added to the general watch-only | // all Scripts (i.e. also all PubKeys) are added to the general watch-only | ||||
// set | // set | ||||
BOOST_CHECK(!wallet.HaveWatchOnly(p2pk)); | BOOST_CHECK(!spk_man->HaveWatchOnly(p2pk)); | ||||
wallet.LoadWatchOnly(p2pk); | spk_man->LoadWatchOnly(p2pk); | ||||
BOOST_CHECK(wallet.HaveWatchOnly(p2pk)); | BOOST_CHECK(spk_man->HaveWatchOnly(p2pk)); | ||||
// only PubKeys on the curve shall be added to the watch-only address -> | // only PubKeys on the curve shall be added to the watch-only address -> | ||||
// PubKey map | // PubKey map | ||||
bool is_pubkey_fully_valid = add_pubkey.IsFullyValid(); | bool is_pubkey_fully_valid = add_pubkey.IsFullyValid(); | ||||
if (is_pubkey_fully_valid) { | if (is_pubkey_fully_valid) { | ||||
BOOST_CHECK(wallet.GetWatchPubKey(add_address, found_pubkey)); | BOOST_CHECK(spk_man->GetWatchPubKey(add_address, found_pubkey)); | ||||
BOOST_CHECK(found_pubkey == add_pubkey); | BOOST_CHECK(found_pubkey == add_pubkey); | ||||
} else { | } else { | ||||
BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey)); | BOOST_CHECK(!spk_man->GetWatchPubKey(add_address, found_pubkey)); | ||||
// passed key is unchanged | // passed key is unchanged | ||||
BOOST_CHECK(found_pubkey == CPubKey()); | BOOST_CHECK(found_pubkey == CPubKey()); | ||||
} | } | ||||
wallet.RemoveWatchOnly(p2pk); | AssertLockHeld(spk_man->cs_wallet); | ||||
BOOST_CHECK(!wallet.HaveWatchOnly(p2pk)); | spk_man->RemoveWatchOnly(p2pk); | ||||
BOOST_CHECK(!spk_man->HaveWatchOnly(p2pk)); | |||||
if (is_pubkey_fully_valid) { | if (is_pubkey_fully_valid) { | ||||
BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey)); | BOOST_CHECK(!spk_man->GetWatchPubKey(add_address, found_pubkey)); | ||||
// passed key is unchanged | // passed key is unchanged | ||||
BOOST_CHECK(found_pubkey == add_pubkey); | BOOST_CHECK(found_pubkey == add_pubkey); | ||||
} | } | ||||
} | } | ||||
// Cryptographically invalidate a PubKey whilst keeping length and first byte | // Cryptographically invalidate a PubKey whilst keeping length and first byte | ||||
static void PollutePubKey(CPubKey &pubkey) { | static void PollutePubKey(CPubKey &pubkey) { | ||||
std::vector<uint8_t> pubkey_raw(pubkey.begin(), pubkey.end()); | std::vector<uint8_t> pubkey_raw(pubkey.begin(), pubkey.end()); | ||||
std::fill(pubkey_raw.begin() + 1, pubkey_raw.end(), 0); | std::fill(pubkey_raw.begin() + 1, pubkey_raw.end(), 0); | ||||
pubkey = CPubKey(pubkey_raw); | pubkey = CPubKey(pubkey_raw); | ||||
assert(!pubkey.IsFullyValid()); | assert(!pubkey.IsFullyValid()); | ||||
assert(pubkey.IsValid()); | assert(pubkey.IsValid()); | ||||
} | } | ||||
// Test watch-only wallet logic for PubKeys | // Test watch-only logic for PubKeys | ||||
BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys) { | BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys) { | ||||
CKey key; | CKey key; | ||||
CPubKey pubkey; | CPubKey pubkey; | ||||
LegacyScriptPubKeyMan *spk_man = m_wallet.GetLegacyScriptPubKeyMan(); | |||||
BOOST_CHECK(!m_wallet.HaveWatchOnly()); | BOOST_CHECK(!spk_man->HaveWatchOnly()); | ||||
// uncompressed valid PubKey | // uncompressed valid PubKey | ||||
key.MakeNewKey(false); | key.MakeNewKey(false); | ||||
pubkey = key.GetPubKey(); | pubkey = key.GetPubKey(); | ||||
assert(!pubkey.IsCompressed()); | assert(!pubkey.IsCompressed()); | ||||
TestWatchOnlyPubKey(m_wallet, pubkey); | TestWatchOnlyPubKey(spk_man, pubkey); | ||||
// uncompressed cryptographically invalid PubKey | // uncompressed cryptographically invalid PubKey | ||||
PollutePubKey(pubkey); | PollutePubKey(pubkey); | ||||
TestWatchOnlyPubKey(m_wallet, pubkey); | TestWatchOnlyPubKey(spk_man, pubkey); | ||||
// compressed valid PubKey | // compressed valid PubKey | ||||
key.MakeNewKey(true); | key.MakeNewKey(true); | ||||
pubkey = key.GetPubKey(); | pubkey = key.GetPubKey(); | ||||
assert(pubkey.IsCompressed()); | assert(pubkey.IsCompressed()); | ||||
TestWatchOnlyPubKey(m_wallet, pubkey); | TestWatchOnlyPubKey(spk_man, pubkey); | ||||
// compressed cryptographically invalid PubKey | // compressed cryptographically invalid PubKey | ||||
PollutePubKey(pubkey); | PollutePubKey(pubkey); | ||||
TestWatchOnlyPubKey(m_wallet, pubkey); | TestWatchOnlyPubKey(spk_man, pubkey); | ||||
// invalid empty PubKey | // invalid empty PubKey | ||||
pubkey = CPubKey(); | pubkey = CPubKey(); | ||||
TestWatchOnlyPubKey(m_wallet, pubkey); | TestWatchOnlyPubKey(spk_man, pubkey); | ||||
} | } | ||||
class ListCoinsTestingSetup : public TestChain100Setup { | class ListCoinsTestingSetup : public TestChain100Setup { | ||||
public: | public: | ||||
ListCoinsTestingSetup() { | ListCoinsTestingSetup() { | ||||
CreateAndProcessBlock({}, | CreateAndProcessBlock({}, | ||||
GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | ||||
wallet = | wallet = | ||||
▲ Show 20 Lines • Show All 139 Lines • Show Last 20 Lines |