mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-05-31 16:24:48 +02:00
Merge #11687: External wallet files
be8ab7d08Create new wallet databases as directories rather than files (Russell Yanofsky)26c06f24eAllow wallet files not in -walletdir directory (Russell Yanofsky)d8a99f65eAllow wallet files in multiple directories (Russell Yanofsky) Pull request description: This change consists of three commits: * The first commit is a pure refactoring that removes the restriction that two wallets can only be opened at the same time if they are contained in the same directory. * The second commit removes the restriction that `-wallet` filenames can only refer to files in the `-walletdir` directory. * The third commit makes second commit a little safer by changing bitcoin to create wallet databases as directories rather than files, so they can be safely backed up. All three commits should be straightforward: * The first commit adds around 20 lines of new code and then updates a bunch of function signatures (generally updating them to take plain fs::path parameters, instead of combinations of strings, fs::paths, and objects like CDBEnv and CWalletDBWrapper). * The second commit removes two `-wallet` filename checks and adds some test cases to the multiwallet unit test. * The third commit just changes the mapping from specified wallet paths to bdb environment & data paths. --- **Note:** For anybody looking at this PR for the first time, I think you can skip the comments before _20 Nov_ and start reading at https://github.com/bitcoin/bitcoin/pull/11687#issuecomment-345625565. Comments before _20 Nov_ were about an earlier version of the PR that didn't include the third commit, and then confusion from not seeing the first commit. Tree-SHA512: 00bbb120fe0df847cf57014f75f1f7f1f58b0b62fa0b3adab4560163ebdfe06ccdfff33b4231693f03c5dc23601cb41954a07bcea9a4919c8d42f7d62bcf6024
This commit is contained in:
@@ -13,13 +13,13 @@
|
||||
BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup)
|
||||
|
||||
static void
|
||||
GetResults(CWallet *wallet, std::map<CAmount, CAccountingEntry>& results)
|
||||
GetResults(CWallet& wallet, std::map<CAmount, CAccountingEntry>& results)
|
||||
{
|
||||
std::list<CAccountingEntry> aes;
|
||||
|
||||
results.clear();
|
||||
BOOST_CHECK(wallet->ReorderTransactions() == DB_LOAD_OK);
|
||||
wallet->ListAccountCreditDebit("", aes);
|
||||
BOOST_CHECK(wallet.ReorderTransactions() == DB_LOAD_OK);
|
||||
wallet.ListAccountCreditDebit("", aes);
|
||||
for (CAccountingEntry& ae : aes)
|
||||
{
|
||||
results[ae.nOrderPos] = ae;
|
||||
@@ -33,28 +33,28 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
||||
CAccountingEntry ae;
|
||||
std::map<CAmount, CAccountingEntry> results;
|
||||
|
||||
LOCK(pwalletMain->cs_wallet);
|
||||
LOCK(m_wallet.cs_wallet);
|
||||
|
||||
ae.strAccount = "";
|
||||
ae.nCreditDebit = 1;
|
||||
ae.nTime = 1333333333;
|
||||
ae.strOtherAccount = "b";
|
||||
ae.strComment = "";
|
||||
pwalletMain->AddAccountingEntry(ae);
|
||||
m_wallet.AddAccountingEntry(ae);
|
||||
|
||||
wtx.mapValue["comment"] = "z";
|
||||
pwalletMain->AddToWallet(wtx);
|
||||
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
||||
m_wallet.AddToWallet(wtx);
|
||||
vpwtx.push_back(&m_wallet.mapWallet[wtx.GetHash()]);
|
||||
vpwtx[0]->nTimeReceived = (unsigned int)1333333335;
|
||||
vpwtx[0]->nOrderPos = -1;
|
||||
|
||||
ae.nTime = 1333333336;
|
||||
ae.strOtherAccount = "c";
|
||||
pwalletMain->AddAccountingEntry(ae);
|
||||
m_wallet.AddAccountingEntry(ae);
|
||||
|
||||
GetResults(pwalletMain.get(), results);
|
||||
GetResults(m_wallet, results);
|
||||
|
||||
BOOST_CHECK(pwalletMain->nOrderPosNext == 3);
|
||||
BOOST_CHECK(m_wallet.nOrderPosNext == 3);
|
||||
BOOST_CHECK(2 == results.size());
|
||||
BOOST_CHECK(results[0].nTime == 1333333333);
|
||||
BOOST_CHECK(results[0].strComment.empty());
|
||||
@@ -65,13 +65,13 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
||||
|
||||
ae.nTime = 1333333330;
|
||||
ae.strOtherAccount = "d";
|
||||
ae.nOrderPos = pwalletMain->IncOrderPosNext();
|
||||
pwalletMain->AddAccountingEntry(ae);
|
||||
ae.nOrderPos = m_wallet.IncOrderPosNext();
|
||||
m_wallet.AddAccountingEntry(ae);
|
||||
|
||||
GetResults(pwalletMain.get(), results);
|
||||
GetResults(m_wallet, results);
|
||||
|
||||
BOOST_CHECK(results.size() == 3);
|
||||
BOOST_CHECK(pwalletMain->nOrderPosNext == 4);
|
||||
BOOST_CHECK(m_wallet.nOrderPosNext == 4);
|
||||
BOOST_CHECK(results[0].nTime == 1333333333);
|
||||
BOOST_CHECK(1 == vpwtx[0]->nOrderPos);
|
||||
BOOST_CHECK(results[2].nTime == 1333333336);
|
||||
@@ -85,8 +85,8 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
||||
++tx.nLockTime; // Just to change the hash :)
|
||||
wtx.SetTx(MakeTransactionRef(std::move(tx)));
|
||||
}
|
||||
pwalletMain->AddToWallet(wtx);
|
||||
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
||||
m_wallet.AddToWallet(wtx);
|
||||
vpwtx.push_back(&m_wallet.mapWallet[wtx.GetHash()]);
|
||||
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
|
||||
|
||||
wtx.mapValue["comment"] = "x";
|
||||
@@ -95,15 +95,15 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
||||
++tx.nLockTime; // Just to change the hash :)
|
||||
wtx.SetTx(MakeTransactionRef(std::move(tx)));
|
||||
}
|
||||
pwalletMain->AddToWallet(wtx);
|
||||
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
||||
m_wallet.AddToWallet(wtx);
|
||||
vpwtx.push_back(&m_wallet.mapWallet[wtx.GetHash()]);
|
||||
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
|
||||
vpwtx[2]->nOrderPos = -1;
|
||||
|
||||
GetResults(pwalletMain.get(), results);
|
||||
GetResults(m_wallet, results);
|
||||
|
||||
BOOST_CHECK(results.size() == 3);
|
||||
BOOST_CHECK(pwalletMain->nOrderPosNext == 6);
|
||||
BOOST_CHECK(m_wallet.nOrderPosNext == 6);
|
||||
BOOST_CHECK(0 == vpwtx[2]->nOrderPos);
|
||||
BOOST_CHECK(results[1].nTime == 1333333333);
|
||||
BOOST_CHECK(2 == vpwtx[0]->nOrderPos);
|
||||
@@ -116,12 +116,12 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
||||
ae.nTime = 1333333334;
|
||||
ae.strOtherAccount = "e";
|
||||
ae.nOrderPos = -1;
|
||||
pwalletMain->AddAccountingEntry(ae);
|
||||
m_wallet.AddAccountingEntry(ae);
|
||||
|
||||
GetResults(pwalletMain.get(), results);
|
||||
GetResults(m_wallet, results);
|
||||
|
||||
BOOST_CHECK(results.size() == 4);
|
||||
BOOST_CHECK(pwalletMain->nOrderPosNext == 7);
|
||||
BOOST_CHECK(m_wallet.nOrderPosNext == 7);
|
||||
BOOST_CHECK(0 == vpwtx[2]->nOrderPos);
|
||||
BOOST_CHECK(results[1].nTime == 1333333333);
|
||||
BOOST_CHECK(2 == vpwtx[0]->nOrderPos);
|
||||
|
||||
@@ -6,26 +6,21 @@
|
||||
|
||||
#include <rpc/server.h>
|
||||
#include <wallet/db.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
|
||||
TestingSetup(chainName)
|
||||
TestingSetup(chainName), m_wallet("mock", CWalletDBWrapper::CreateMock())
|
||||
{
|
||||
bitdb.MakeMock();
|
||||
bool fFirstRun;
|
||||
g_address_type = OUTPUT_TYPE_DEFAULT;
|
||||
g_change_type = OUTPUT_TYPE_DEFAULT;
|
||||
std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, "wallet_test.dat"));
|
||||
pwalletMain = MakeUnique<CWallet>(std::move(dbw));
|
||||
pwalletMain->LoadWallet(fFirstRun);
|
||||
RegisterValidationInterface(pwalletMain.get());
|
||||
m_wallet.LoadWallet(fFirstRun);
|
||||
RegisterValidationInterface(&m_wallet);
|
||||
|
||||
RegisterWalletRPCCommands(tableRPC);
|
||||
}
|
||||
|
||||
WalletTestingSetup::~WalletTestingSetup()
|
||||
{
|
||||
UnregisterValidationInterface(pwalletMain.get());
|
||||
|
||||
bitdb.Flush(true);
|
||||
bitdb.Reset();
|
||||
UnregisterValidationInterface(&m_wallet);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ struct WalletTestingSetup: public TestingSetup {
|
||||
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
|
||||
~WalletTestingSetup();
|
||||
|
||||
std::unique_ptr<CWallet> pwalletMain;
|
||||
CWallet m_wallet;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@ typedef std::set<CInputCoin> CoinSet;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
|
||||
|
||||
static const CWallet testWallet;
|
||||
static const CWallet testWallet("dummy", CWalletDBWrapper::CreateDummy());
|
||||
static std::vector<COutput> vCoins;
|
||||
|
||||
static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0)
|
||||
@@ -382,7 +382,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||
// Verify ScanForWalletTransactions picks up transactions in both the old
|
||||
// and new block files.
|
||||
{
|
||||
CWallet wallet;
|
||||
CWallet wallet("dummy", CWalletDBWrapper::CreateDummy());
|
||||
AddKey(wallet, coinbaseKey);
|
||||
WalletRescanReserver reserver(&wallet);
|
||||
reserver.reserve();
|
||||
@@ -397,7 +397,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||
// Verify ScanForWalletTransactions only picks transactions in the new block
|
||||
// file.
|
||||
{
|
||||
CWallet wallet;
|
||||
CWallet wallet("dummy", CWalletDBWrapper::CreateDummy());
|
||||
AddKey(wallet, coinbaseKey);
|
||||
WalletRescanReserver reserver(&wallet);
|
||||
reserver.reserve();
|
||||
@@ -409,7 +409,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||
// before the missing block, and success for a key whose creation time is
|
||||
// after.
|
||||
{
|
||||
CWallet wallet;
|
||||
CWallet wallet("dummy", CWalletDBWrapper::CreateDummy());
|
||||
vpwallets.insert(vpwallets.begin(), &wallet);
|
||||
UniValue keys;
|
||||
keys.setArray();
|
||||
@@ -471,7 +471,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||
|
||||
// Import key into wallet and call dumpwallet to create backup file.
|
||||
{
|
||||
CWallet wallet;
|
||||
CWallet wallet("dummy", CWalletDBWrapper::CreateDummy());
|
||||
LOCK(wallet.cs_wallet);
|
||||
wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
|
||||
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
|
||||
@@ -486,7 +486,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
|
||||
// were scanned, and no prior blocks were scanned.
|
||||
{
|
||||
CWallet wallet;
|
||||
CWallet wallet("dummy", CWalletDBWrapper::CreateDummy());
|
||||
|
||||
JSONRPCRequest request;
|
||||
request.params.setArray();
|
||||
@@ -516,7 +516,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||
// debit functions.
|
||||
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
|
||||
{
|
||||
CWallet wallet;
|
||||
CWallet wallet("dummy", CWalletDBWrapper::CreateDummy());
|
||||
CWalletTx wtx(&wallet, MakeTransactionRef(coinbaseTxns.back()));
|
||||
LOCK2(cs_main, wallet.cs_wallet);
|
||||
wtx.hashBlock = chainActive.Tip()->GetBlockHash();
|
||||
@@ -562,27 +562,25 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
|
||||
// expanded to cover more corner cases of smart time logic.
|
||||
BOOST_AUTO_TEST_CASE(ComputeTimeSmart)
|
||||
{
|
||||
CWallet wallet;
|
||||
|
||||
// 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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
// 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
|
||||
// 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.
|
||||
SetMockTime(0);
|
||||
@@ -591,12 +589,12 @@ BOOST_AUTO_TEST_CASE(ComputeTimeSmart)
|
||||
BOOST_AUTO_TEST_CASE(LoadReceiveRequests)
|
||||
{
|
||||
CTxDestination dest = CKeyID();
|
||||
LOCK(pwalletMain->cs_wallet);
|
||||
pwalletMain->AddDestData(dest, "misc", "val_misc");
|
||||
pwalletMain->AddDestData(dest, "rr0", "val_rr0");
|
||||
pwalletMain->AddDestData(dest, "rr1", "val_rr1");
|
||||
LOCK(m_wallet.cs_wallet);
|
||||
m_wallet.AddDestData(dest, "misc", "val_misc");
|
||||
m_wallet.AddDestData(dest, "rr0", "val_rr0");
|
||||
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[0], "val_rr0");
|
||||
BOOST_CHECK_EQUAL(values[1], "val_rr1");
|
||||
@@ -608,10 +606,9 @@ public:
|
||||
ListCoinsTestingSetup()
|
||||
{
|
||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||
::bitdb.MakeMock();
|
||||
g_address_type = OUTPUT_TYPE_DEFAULT;
|
||||
g_change_type = OUTPUT_TYPE_DEFAULT;
|
||||
wallet.reset(new CWallet(std::unique_ptr<CWalletDBWrapper>(new CWalletDBWrapper(&bitdb, "wallet_test.dat"))));
|
||||
wallet = MakeUnique<CWallet>("mock", CWalletDBWrapper::CreateMock());
|
||||
bool firstRun;
|
||||
wallet->LoadWallet(firstRun);
|
||||
AddKey(*wallet, coinbaseKey);
|
||||
@@ -623,8 +620,6 @@ public:
|
||||
~ListCoinsTestingSetup()
|
||||
{
|
||||
wallet.reset();
|
||||
::bitdb.Flush(true);
|
||||
::bitdb.Reset();
|
||||
}
|
||||
|
||||
CWalletTx& AddTx(CRecipient recipient)
|
||||
|
||||
Reference in New Issue
Block a user