Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/test/wallet_tests.cpp
| Show First 20 Lines • Show All 78 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(GetConfig()); | ||||
| 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 328 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(GetConfig()); | ||||
| 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 14 Lines | BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { | ||||
| 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(); | ||||
| // 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(GetConfig()); | ||||
| LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
| wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | ||||
| BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip)); | BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip)); | ||||
| 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(GetConfig()); | ||||
| LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
| wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); | ||||
| BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(oldTip)); | BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(oldTip)); | ||||
| 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(GetConfig()); | ||||
| 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 All 20 Lines | // after. | ||||
| "missing.\"}},{\"success\":true}]", | "missing.\"}},{\"success\":true}]", | ||||
| newTip->GetBlockTimeMax())); | newTip->GetBlockTimeMax())); | ||||
| vpwallets.erase(vpwallets.begin()); | vpwallets.erase(vpwallets.begin()); | ||||
| } | } | ||||
| // Verify ScanForWalletTransactions does not return null when the scan is | // Verify ScanForWalletTransactions does not return null when the scan is | ||||
| // elided due to the nTimeFirstKey optimization. | // elided due to the nTimeFirstKey optimization. | ||||
| { | { | ||||
| CWallet wallet(Params()); | CWallet wallet(GetConfig()); | ||||
| { | { | ||||
| LOCK(wallet.cs_wallet); | LOCK(wallet.cs_wallet); | ||||
| wallet.UpdateTimeFirstKey(newTip->GetBlockTime() + 7200 + 1); | wallet.UpdateTimeFirstKey(newTip->GetBlockTime() + 7200 + 1); | ||||
| } | } | ||||
| BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(newTip)); | BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(newTip)); | ||||
| } | } | ||||
| } | } | ||||
| Show All 23 Lines | BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { | ||||
| SetMockTime(KEY_TIME); | SetMockTime(KEY_TIME); | ||||
| coinbaseTxns.emplace_back( | coinbaseTxns.emplace_back( | ||||
| *CreateAndProcessBlock({}, | *CreateAndProcessBlock({}, | ||||
| GetScriptForRawPubKey(coinbaseKey.GetPubKey())) | GetScriptForRawPubKey(coinbaseKey.GetPubKey())) | ||||
| .vtx[0]); | .vtx[0]); | ||||
| // 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(GetConfig()); | ||||
| 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(GetConfig()); | ||||
| 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); | ||||
| BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3); | BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3); | ||||
| Show All 11 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(GetConfig()); | ||||
| 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(0)); | BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), Amount(0)); | ||||
| Show All 26 Lines | static int64_t AddTx(CWallet &wallet, uint32_t lockTime, int64_t mockTime, | ||||
| } | } | ||||
| wallet.AddToWallet(wtx); | wallet.AddToWallet(wtx); | ||||
| 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()); | CWallet wallet(GetConfig()); | ||||
| // 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(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(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. | ||||
| Show All 18 Lines | |||||