Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/test/wallet_tests.cpp
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | std::pair<CoinSet::iterator, CoinSet::iterator> ret = | ||||
mismatch(a.begin(), a.end(), b.begin()); | mismatch(a.begin(), a.end(), b.begin()); | ||||
return ret.first == a.end() && ret.second == b.end(); | return ret.first == a.end() && ret.second == b.end(); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(coin_selection_tests) { | BOOST_AUTO_TEST_CASE(coin_selection_tests) { | ||||
CoinSet setCoinsRet, setCoinsRet2; | CoinSet setCoinsRet, setCoinsRet2; | ||||
Amount nValueRet; | Amount nValueRet; | ||||
const CWallet wallet(Params()); | const CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
LOCK(walletCriticalSection); | LOCK(walletCriticalSection); | ||||
// test multiple times to allow for differences in the shuffle order | // test multiple times to allow for differences in the shuffle order | ||||
for (int i = 0; i < RUN_TESTS; i++) { | for (int i = 0; i < RUN_TESTS; i++) { | ||||
empty_wallet(); | empty_wallet(); | ||||
// with an empty wallet we can't even pay one cent | // with an empty wallet we can't even pay one cent | ||||
BOOST_CHECK(!wallet.SelectCoinsMinConf(1 * CENT, 1, 6, 0, vCoins, | BOOST_CHECK(!wallet.SelectCoinsMinConf(1 * CENT, 1, 6, 0, vCoins, | ||||
▲ Show 20 Lines • Show All 332 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(coin_selection_tests) { | ||||
} | } | ||||
empty_wallet(); | empty_wallet(); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(ApproximateBestSubset) { | BOOST_AUTO_TEST_CASE(ApproximateBestSubset) { | ||||
CoinSet setCoinsRet; | CoinSet setCoinsRet; | ||||
Amount nValueRet; | Amount nValueRet; | ||||
const CWallet wallet(Params()); | const CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
LOCK(walletCriticalSection); | LOCK(walletCriticalSection); | ||||
empty_wallet(); | empty_wallet(); | ||||
// Test vValue sort order | // Test vValue sort order | ||||
for (int i = 0; i < 1000; i++) { | for (int i = 0; i < 1000; i++) { | ||||
add_coin(wallet, 1000 * COIN); | add_coin(wallet, 1000 * COIN); | ||||
} | } | ||||
Show All 20 Lines | BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { | ||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | ||||
CBlockIndex *newTip = chainActive.Tip(); | CBlockIndex *newTip = chainActive.Tip(); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Verify ScanForWalletTransactions picks up transactions in both the old | // Verify ScanForWalletTransactions picks up transactions in both the old | ||||
// and new block files. | // and new block files. | ||||
{ | { | ||||
CWallet wallet(Params()); | CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
AddKey(wallet, coinbaseKey); | AddKey(wallet, coinbaseKey); | ||||
WalletRescanReserver reserver(&wallet); | WalletRescanReserver reserver(&wallet); | ||||
reserver.reserve(); | reserver.reserve(); | ||||
BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions( | BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions( | ||||
oldTip, nullptr, reserver)); | oldTip, nullptr, reserver)); | ||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); | BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); | ||||
} | } | ||||
// Prune the older block file. | // Prune the older block file. | ||||
PruneOneBlockFile(oldTip->GetBlockPos().nFile); | PruneOneBlockFile(oldTip->GetBlockPos().nFile); | ||||
UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); | UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); | ||||
// Verify ScanForWalletTransactions only picks transactions in the new block | // Verify ScanForWalletTransactions only picks transactions in the new block | ||||
// file. | // file. | ||||
{ | { | ||||
CWallet wallet(Params()); | CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
AddKey(wallet, coinbaseKey); | AddKey(wallet, coinbaseKey); | ||||
WalletRescanReserver reserver(&wallet); | WalletRescanReserver reserver(&wallet); | ||||
reserver.reserve(); | reserver.reserve(); | ||||
BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions( | BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions( | ||||
oldTip, nullptr, reserver)); | oldTip, nullptr, reserver)); | ||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); | BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); | ||||
} | } | ||||
// Verify importmulti RPC returns failure for a key whose creation time is | // Verify importmulti RPC returns failure for a key whose creation time is | ||||
// before the missing block, and success for a key whose creation time is | // before the missing block, and success for a key whose creation time is | ||||
// after. | // after. | ||||
{ | { | ||||
CWallet wallet(Params()); | CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
vpwallets.insert(vpwallets.begin(), &wallet); | vpwallets.insert(vpwallets.begin(), &wallet); | ||||
UniValue keys; | UniValue keys; | ||||
keys.setArray(); | keys.setArray(); | ||||
UniValue key; | UniValue key; | ||||
key.setObject(); | key.setObject(); | ||||
key.pushKV("scriptPubKey", | key.pushKV("scriptPubKey", | ||||
HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey()))); | HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey()))); | ||||
key.pushKV("timestamp", 0); | key.pushKV("timestamp", 0); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | coinbaseTxns.emplace_back( | ||||
*CreateAndProcessBlock({}, | *CreateAndProcessBlock({}, | ||||
GetScriptForRawPubKey(coinbaseKey.GetPubKey())) | GetScriptForRawPubKey(coinbaseKey.GetPubKey())) | ||||
.vtx[0]); | .vtx[0]); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Import key into wallet and call dumpwallet to create backup file. | // Import key into wallet and call dumpwallet to create backup file. | ||||
{ | { | ||||
CWallet wallet(Params()); | CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = | wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = | ||||
KEY_TIME; | KEY_TIME; | ||||
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | ||||
JSONRPCRequest request; | JSONRPCRequest request; | ||||
request.params.setArray(); | request.params.setArray(); | ||||
request.params.push_back((pathTemp / "wallet.backup").string()); | request.params.push_back((pathTemp / "wallet.backup").string()); | ||||
vpwallets.insert(vpwallets.begin(), &wallet); | vpwallets.insert(vpwallets.begin(), &wallet); | ||||
::dumpwallet(GetConfig(), request); | ::dumpwallet(GetConfig(), request); | ||||
} | } | ||||
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME | // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME | ||||
// were scanned, and no prior blocks were scanned. | // were scanned, and no prior blocks were scanned. | ||||
{ | { | ||||
CWallet wallet(Params()); | CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
JSONRPCRequest request; | JSONRPCRequest request; | ||||
request.params.setArray(); | request.params.setArray(); | ||||
request.params.push_back((pathTemp / "wallet.backup").string()); | request.params.push_back((pathTemp / "wallet.backup").string()); | ||||
vpwallets[0] = &wallet; | vpwallets[0] = &wallet; | ||||
::importwallet(GetConfig(), request); | ::importwallet(GetConfig(), request); | ||||
LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
Show All 12 Lines | |||||
// Check that GetImmatureCredit() returns a newly calculated value instead of | // Check that GetImmatureCredit() returns a newly calculated value instead of | ||||
// the cached value after a MarkDirty() call. | // the cached value after a MarkDirty() call. | ||||
// | // | ||||
// 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) { | ||||
CWallet wallet(Params()); | CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); | ||||
CWalletTx wtx(&wallet, MakeTransactionRef(coinbaseTxns.back())); | CWalletTx wtx(&wallet, MakeTransactionRef(coinbaseTxns.back())); | ||||
LOCK2(cs_main, wallet.cs_wallet); | LOCK2(cs_main, wallet.cs_wallet); | ||||
wtx.hashBlock = chainActive.Tip()->GetBlockHash(); | wtx.hashBlock = chainActive.Tip()->GetBlockHash(); | ||||
wtx.nIndex = 0; | wtx.nIndex = 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(), Amount::zero()); | BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), Amount::zero()); | ||||
Show All 31 Lines | static int64_t AddTx(CWallet &wallet, uint32_t lockTime, int64_t mockTime, | ||||
} | } | ||||
LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
return wallet.mapWallet.at(wtx.GetId()).nTimeSmart; | return wallet.mapWallet.at(wtx.GetId()).nTimeSmart; | ||||
} | } | ||||
// Simple test to verify assignment of CWalletTx::nSmartTime value. Could be | // Simple test to verify assignment of CWalletTx::nSmartTime value. Could be | ||||
// expanded to cover more corner cases of smart time logic. | // expanded to cover more corner cases of smart time logic. | ||||
BOOST_AUTO_TEST_CASE(ComputeTimeSmart) { | BOOST_AUTO_TEST_CASE(ComputeTimeSmart) { | ||||
CWallet wallet(Params()); | |||||
// New transaction should use clock time if lower than block time. | // New transaction should use clock time if lower than block time. | ||||
BOOST_CHECK_EQUAL(AddTx(wallet, 1, 100, 120), 100); | BOOST_CHECK_EQUAL(AddTx(m_wallet, 1, 100, 120), 100); | ||||
// Test that updating existing transaction does not change smart time. | // Test that updating existing transaction does not change smart time. | ||||
BOOST_CHECK_EQUAL(AddTx(wallet, 1, 200, 220), 100); | BOOST_CHECK_EQUAL(AddTx(m_wallet, 1, 200, 220), 100); | ||||
// New transaction should use clock time if there's no block time. | // New transaction should use clock time if there's no block time. | ||||
BOOST_CHECK_EQUAL(AddTx(wallet, 2, 300, 0), 300); | BOOST_CHECK_EQUAL(AddTx(m_wallet, 2, 300, 0), 300); | ||||
// New transaction should use block time if lower than clock time. | // New transaction should use block time if lower than clock time. | ||||
BOOST_CHECK_EQUAL(AddTx(wallet, 3, 420, 400), 400); | BOOST_CHECK_EQUAL(AddTx(m_wallet, 3, 420, 400), 400); | ||||
// New transaction should use latest entry time if higher than | // New transaction should use latest entry time if higher than | ||||
// min(block time, clock time). | // min(block time, clock time). | ||||
BOOST_CHECK_EQUAL(AddTx(wallet, 4, 500, 390), 400); | BOOST_CHECK_EQUAL(AddTx(m_wallet, 4, 500, 390), 400); | ||||
// If there are future entries, new transaction should use time of the | // If there are future entries, new transaction should use time of the | ||||
// newest entry that is no more than 300 seconds ahead of the clock time. | // newest entry that is no more than 300 seconds ahead of the clock time. | ||||
BOOST_CHECK_EQUAL(AddTx(wallet, 5, 50, 600), 300); | BOOST_CHECK_EQUAL(AddTx(m_wallet, 5, 50, 600), 300); | ||||
// Reset mock time for other tests. | // Reset mock time for other tests. | ||||
SetMockTime(0); | SetMockTime(0); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(LoadReceiveRequests) { | BOOST_AUTO_TEST_CASE(LoadReceiveRequests) { | ||||
CTxDestination dest = CKeyID(); | CTxDestination dest = CKeyID(); | ||||
LOCK(pwalletMain->cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
pwalletMain->AddDestData(dest, "misc", "val_misc"); | m_wallet.AddDestData(dest, "misc", "val_misc"); | ||||
pwalletMain->AddDestData(dest, "rr0", "val_rr0"); | m_wallet.AddDestData(dest, "rr0", "val_rr0"); | ||||
pwalletMain->AddDestData(dest, "rr1", "val_rr1"); | m_wallet.AddDestData(dest, "rr1", "val_rr1"); | ||||
auto values = pwalletMain->GetDestValues("rr"); | auto values = m_wallet.GetDestValues("rr"); | ||||
BOOST_CHECK_EQUAL(values.size(), 2); | BOOST_CHECK_EQUAL(values.size(), 2); | ||||
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"); | ||||
} | } | ||||
class ListCoinsTestingSetup : public TestChain100Setup { | class ListCoinsTestingSetup : public TestChain100Setup { | ||||
public: | public: | ||||
ListCoinsTestingSetup() { | ListCoinsTestingSetup() { | ||||
CreateAndProcessBlock({}, | CreateAndProcessBlock({}, | ||||
GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | GetScriptForRawPubKey(coinbaseKey.GetPubKey())); | ||||
::bitdb.MakeMock(); | wallet = std::make_unique<CWallet>(Params(), "mock", | ||||
wallet.reset(new CWallet( | CWalletDBWrapper::CreateMock()); | ||||
Params(), std::unique_ptr<CWalletDBWrapper>( | |||||
new CWalletDBWrapper(&bitdb, "wallet_test.dat")))); | |||||
bool firstRun; | bool firstRun; | ||||
wallet->LoadWallet(firstRun); | wallet->LoadWallet(firstRun); | ||||
AddKey(*wallet, coinbaseKey); | AddKey(*wallet, coinbaseKey); | ||||
WalletRescanReserver reserver(wallet.get()); | WalletRescanReserver reserver(wallet.get()); | ||||
reserver.reserve(); | reserver.reserve(); | ||||
wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, | wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, | ||||
reserver); | reserver); | ||||
} | } | ||||
~ListCoinsTestingSetup() { | ~ListCoinsTestingSetup() { wallet.reset(); } | ||||
wallet.reset(); | |||||
::bitdb.Flush(true); | |||||
::bitdb.Reset(); | |||||
} | |||||
CWalletTx &AddTx(CRecipient recipient) { | CWalletTx &AddTx(CRecipient recipient) { | ||||
CTransactionRef tx; | CTransactionRef tx; | ||||
CReserveKey reservekey(wallet.get()); | CReserveKey reservekey(wallet.get()); | ||||
Amount fee; | Amount fee; | ||||
int changePos = -1; | int changePos = -1; | ||||
std::string error; | std::string error; | ||||
CCoinControl dummy; | CCoinControl dummy; | ||||
▲ Show 20 Lines • Show All 72 Lines • Show Last 20 Lines |