Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Dynamically Loadable Multiple Wallet Support Complete!!! #2124

Closed
wants to merge 38 commits into from
@CodeShark

bitcoind now supports loading more than one wallet at once.

A singleton object of type CWalletManager now exists. It handles dynamic loading/unloading and synchronization of wallets and allows different parts of the application to access wallets by name.

A new CWallet* parameter has been added to the RPC functions. Functions which do not use a wallet simply ignore it. In addition, a new field has been added to CRPCCommand that tells us whether or not the function can be called on a wallet.

Wallet-specific information has been removed from RPC method getinfo. Instead, getinfo just reports how many
wallets are currently loaded. Detailed wallet info is now available via the listwallets method.

Four new RPC methods have been added:

  • listwallets
    Returns an array containing wallet information.

  • usewallet <walletname> <method> [params]
    Allows you to apply existing RPC commands to different wallets.
    A default wallet named the empty string is always loaded and is used if calls are made without usewallet.
    Example: bitcoind usewallet foo listreceivedbyaddress 0 true
    (thanks, gmaxwell, for the idea)

  • loadwallet <walletname> [rescan=false] [upgradewallet=false] [maxversion=(latest)]
    Dynamically loads an existing wallet file wallet-<walletname>.dat.
    If no wallet file exists a new wallet is created. The default wallet file is always called wallet.dat.

  • unloadwallet <walletname>

To specify additional wallets at startup, use option -usewallet=foo -usewallet=bar etc...as detailed here: #2124 (comment) and CodeShark@9d201cf

TODO:

  • Clean up I/O in CWalletManager::LoadWallet - debug, error, and UI output functions.
  • Check synchronization code.
  • Test mining functionality. Allow RPC mining on arbitrary wallets.
  • Integrate with Qt.
@CodeShark

It's a work in progress and can certainly be improved. I welcome all comments, suggestions, criticisms, and witty insults.

@Diapolo

Would it be better or possible to use references instead of pointers in your code?

@CodeShark

Possible, sure. Better, why?

@CodeShark

The sanity test failed because the test suite uses the old RPC function prototype. I was still able to build and run using

  • make -f makefile.unix bitcoind
@rebroad

This may be an opportunity to move away from the wallets being called "wallet.dat", which makes it all the more easier for malware to steal the contents.

@CodeShark

You can now specify additional wallets in the config file or via command line arguments:

usewallet=foo

or

bitcoind -usewallet=foo

A default wallet called "" in the RPC and using file "wallet.dat" is always loaded, as to not break compatibility with the master branch. Therefore, additional wallets should neither be called "default" nor "wallet".

The wallet will be stored in a file called wallet-foo.dat. If the wallet doesn't yet exist, it will be created the first time the wallet is loaded.

CodeShark added some commits
@CodeShark CodeShark Added multiple wallet support
=============================

A new global structure called pWalletMap has been added. Upon initialization, multiple wallets can be loaded.

A new CWallet* parameter has been added to the RPC functions. Functions which do not use a wallet simply ignore it. In addition, a new field has been added to CRPCCommand that tells us whether or not the function uses a wallet.

Two new RPC methods have been added:
  1) listwallets - Returns an array containing wallet names.
  2) usewallet - Prefix existing wallet RPC calls with usewallet <walletname> to use a particular wallet. If no wallet is specified, the default wallet is used.
    example: bitcoind usewallet foo listreceivedbyaddress 0 true

TODO:
  1) Get wallet names from bitcoin.conf in init.cpp.
  2) Change help RPC so that the message does not depend on wallet state (i.e. walletpassphrase RPC call)
71c63e3
@CodeShark CodeShark Added CWallet* parameter to RPC test suite and a CWalletMap instance …
…to test_bitcoin.cpp
4a6b0e2
@CodeShark CodeShark Fixed RPC issues detected by test suite. 158ce39
@CodeShark CodeShark Added loading of wallet names and files from -usewallet arguments
=================================================================

You can now specify additional wallets in the config file or via command line arguments:

	usewallet=foo

or

	bitcoind -usewallet=foo

A default wallet called "default" in the RPC and using file "wallet.dat" is always loaded, as to not break compatibility with the master branch. Therefore, additional wallets should neither be called "default" nor "wallet" nor anything else that might conflict with other filenames in the .bitcoin directory.

The wallet will be stored in a file called foo.dat. If the wallet doesn't yet exist, it will be created the first time bitcoind is run.

TODO: Ensure filename collisions cannot occur. Perhaps allow the wallet files to be arbitrarily named rather than tied to their identifier.
1b640c1
@CodeShark CodeShark TxMemPool::accept() calls SyncWithWallets(), so all mempool transacti…
…ons are synched automatically without having to call SyncWithWallets() explicitly. This is important when sending between two wallets in a single bitcoind instance so that the receiving wallet is alerted of the transaction immediately.

Removed calls to SyncWithWallets() in ProcessMessage() since SyncWithWallets() is already called by tx.AcceptToMemoryPool().

SyncWithWallets() is still called explicitly from CBlock::ConnectBlock() since the transaction never goes through the mempool in this case.
1cdf18b
@CodeShark CodeShark Modified getinfo RPC call to return an array of wallets 27fa196
@CodeShark CodeShark Removed dependency on wallet encryption state for getting help on RPC…
… methods. Help always returns usage info now.
93e6b80
@CodeShark CodeShark usewallet now checks whether method is valid. 0f815bf
@CodeShark

The getinfo RPC method now returns an array of wallets each with wallet-specific information. This change is, unfortunately, not backwards compatible. However, it doesn't really seem to make sense to make this call wallet-specific. And returning an array of wallets seems to be a very useful feature.

@gmaxwell
Owner

An alternative would be to move that data out of getinfo and into a getwallet info. Part of the reason to do that is that the wallet outputs in getinfo can be rather slow already, and doing them for N wallets won't help matters. (Though lets see if anyone else has an opinion, I could be on drugs here)

@CodeShark

I was thinking listwallets should maybe show all this information with a verbose option. Without the verbose option, it would just give a list of the wallet names.

@gmaxwell
Owner

Hm. From the perspective of the RPC as a CLI the use of verbose flags isn't especially discoverable— for something basic like 'get your balances' that is probably worth exposing at the top level. ::shrugs::

@CodeShark

What about making the full info the default and having an option to shorten it? That way interactive users get relevant information while application developers seeking to improve performance have an option to do so if they don't need all that information. Of course we can just have two distinct RPC methods...but I'd rather avoid having too many RPC calls when the semantics are similar.

@CodeShark

I do think that the wallet information should be completely removed from getinfo, though.

Anyhow, this is the kind of stuff that's really easy to implement and change up front but becomes a serious problem to change once people start using it to build applications. I'd also like to hear several more opinions on this before committing to anything specific.

@CodeShark

Another issue I'm wondering about is programmatic access to the config file. We could just append the new wallets to the end of the file whenever they are created - but it would be nice to be able to have tags for sections. Presumably whenever a user creates a new wallet they want it to be loaded at next startup unless they explicitly remove it from the config file.

@mikegogulski

Multiple wallet support came into my head as I was doing #2075 but I left it aside in favor of trying to move the code in the direction of further modularization improvements between the RPC interface and the wallet and the wallet database as a prerequisite. I put off coding there since I expected something like this to come along and because commentary on the pull request died away.

I can't review the code in detail now but this capability needs to happen. Passing CWallet * around is an improvement for sure, definitely better than another global. I'm finding it kinda cringeworth-brittle from an OO perspective, though. It would be lovely to see new RPC functions implemented in ways that drag suitable amounts of code that depends strongly on the wallet's internal representation out along with them the appropriate changes to the wallet object.

Have you tried merging my code? I'll have to look at that later. Multiple wallets are useful for any number of reasons. Certainly the Bitcoin-only accountants and would-be tax collectors of the future aren't going to be running n instances of bitcoind on their desktops.

Ultimate I think the wallet should be decoupled from the rest of the satoshi client. Pushing standarized interfaces down to wallet-object level is somewhere on the road to getting there. You seem to be addressing some modularization issues in other areas though, too.

@CodeShark

As for the OO stuff, I would like to abstract things further and define a listener interface, a transaction store interface, and a key store interface. Technically speaking, a signing agent doesn't even need to store complete transactions. Private keys and unspent outpoints are all it needs. Furthermore, a listening agent could send alerts to other components without the need to store any transactions. For instance, it could just provide filtering.

Having said that, in the interest of seeing these pull requests merged with bitcoin/bitcoin master ASAP, I'm willing to do things incrementally and use whatever structures already exist for now. However, I'd be very interested in giving all this some deeper thought and coming up with a serious reorganization for some later version.

As for now, at the very least it is possible to encapsulate the existing CWallet class much better - and I applaud your efforts.

src/bitcoinrpc.cpp
((6 lines not shown))
try
{
// Execute
Value result;
{
- if (pcmd->unlocked)
- result = pcmd->actor(params, false);
+ if (pcmd->unlocked) {
+ result = pcmd->actor(pWallet, params, false);
+ }
else {
LOCK2(cs_main, pwalletMain->cs_wallet);
@sipa Owner
sipa added a note

This will need to lock the appropriate wallet (if any), not pwalletMain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/init.cpp
@@ -25,6 +25,7 @@
using namespace std;
using namespace boost;
+CWalletMap* pWalletMap;
@sipa Owner
sipa added a note

pWalletMap can be allocated statically, I believe.

A problem is that it is declared in both init.cpp and test_bitcoin.cpp - and these globals must be accessible from rpcwallet.cpp as well, which includes init.h for the externs. I would prefer the wallet RPC calls to be placed in an RPC class which takes a wallet map in its constructor - and then we could remove any dependencies on these externs entirely and restrict the variable scope to init.cpp or the unit test main. But yeah, it could be allocated statically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/wallet.h
@@ -311,6 +311,21 @@ class CWallet : public CCryptoKeyStore
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
};
+/** A CWalletMap associates wallets with names and automatically deallocates them upon destruction.
+ */
+typedef std::map<std::string, CWallet*> wallet_map;
+class CWalletMap
+{
+public:
+ wallet_map wallets;
+
+ ~CWalletMap()
@sipa Owner
sipa added a note

You may want to use an auto_ptr to make this cleanup happen automatically.

I was thinking to expand this class to also handle loading of wallets from config parameters.

Perhaps init.cpp could pass io context stuff to the loader method so that the loader method needn't call printf directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@sipa
Owner

In general: I'm very much in favor of having native support for multiple wallets. Wallet stuff hasn't been a priority for some time, but if necessary I'd like to help to get this working.

Regarding the idea of separating wallets for block chain processing: sure, that's definitely where we need to go in the future. Ideally, I think the code evolves to separate wallet and the rest along a clean interface in a first step indeed. In a second step, we can maybe make them separate processes started from the same binary or even just separate binaries with shared codebase. The final aim should be entirely separate things, either communicating via some private "wallet interconnect protocol" (where several wallets on a trusted network connect to a single validation service), or even turning the wallet processes into standalone SPV clients (with their own blockheader-chain), that can either connect directly to the network, or can connect to a server provide block/tx validation service, simply via the P2P protocol.

@mikegogulski

On the wallet site of things, IMHO, we could think about switching the interface to JSON-RPC for all interaction with the wallet object(s) and database(s), which would eventually enable bitcoin-qt to talk to wallets on report machines over SSL/TLS. That's painful to tackle all at once, though, since there's plenty of code outside the RPC bundle right now that depends on wallet internals and a while lot of methods sticking off of CWallet.

@rebroad

This pull request is confusing me as it's raised by a different user to the user making the commits.. (or maybe I don't understand github correctly). Also, I'm wondering if such a thing as a "roadmap" exists for bitcoind/bitcoin-qt. I'm thinking that perhaps the project could be split into two binaries, one that deals with the P2P stuff and sending/receiving tx/blocks, and the other that deals with purely wallet stuff. Currently bitcoind is slowly becoming bloated with both, and a focus on making the split possible might be useful.

@CodeShark

Both users are me. I don't use my CodeShark identity for pushes, though. CodeShark is reserved for github.

CodeShark added some commits
@CodeShark CodeShark Moved wallet detail information out of getinfo and put it in listwall…
…ets. getinfo now just shows how many wallets are loaded.
b0cae87
@CodeShark CodeShark Moved code for locking a wallet automatically at a certain time from …
…rpcwallet.cpp into CCryptoKeyStore class.

TODO:
  Encapsulate the thread spawning and make the call nonblocking.
  Give each thread a unique name.
2b31fdf
@CodeShark

Is this LOCK really necessary?

CodeShark added some commits
@CodeShark CodeShark Dynamic loading and unloading of wallets.
New Changes:
  - Moved LoadWallet out of init.cpp and into CWalletMap class.
  - Added new RPC methods: loadwallet and unloadwallet.

TODO:
  - Clean up I/O in CWalletMap::LoadWallet - debug, error, and UI output functions.
  - Make sure wallet loading and unloading are thread-safe.
  - Save wallets to bitcoin.conf automatically.
1b51a7f
@CodeShark CodeShark New naming scheme for wallets. Checks for valid character set. CWalle…
…tMap now handles unregistration of wallets from main.

Added linker option to makefiles for boost_regex.
3fd110a
@CodeShark CodeShark More load options at startup.
If at least one -usewallet parameter is given, it will use those parameters to determine which wallets to load at startup.
If no -usewallet parameters are given, it searches the data directory for files named wallet-<walletname>.dat.

Also added -nousewallet parameters which override either -usewallet or the data directory.
9d201cf
@CodeShark

Dynamic wallet loading is essentially complete. An important issue that needs to be resolved prior to any integration is making sure its use of LOCKs on threads is ok. Error handling on initialization is also not super smooth, but that's more an issue with AppInit2 generally. At this point I mostly just want to polish up what's there, fix any potential bugs or serious issues, leave this branch alone, and go work on other features.

src/bitcoinrpc.cpp
@@ -1065,16 +1069,20 @@ void ThreadRPCServer3(void* parg)
!pcmd->okSafeMode)
throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
+ if (!pWallet) pWallet = pwalletMain;

Probably should use pWalletMap->GetDefaultWallet() wherever pwalletMain appears anywhere in the application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/rpcwallet.cpp
((20 lines not shown))
+ objWallet.push_back(Pair("keypoololdest", (boost::int64_t)item.second->GetOldestKeyPoolTime()));
+ obj.push_back(Pair(item.first, objWallet));
+ }
+
+ return obj;
+}
+
+Value usewallet(CWallet* pWallet, const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() < 2)
+ throw runtime_error(
+ "usewallet <walletname> <method> [params]\n"
+ "Selects which wallet to use.");
+
+ string strWalletName = params[0].get_str();
+ wallet_map::iterator it = pWalletMap->wallets.find(strWalletName);

Should use pWalletMap->GetWallet(strWalletMap);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/rpcwallet.cpp
@@ -1572,3 +1538,92 @@ Value listlockunspent(const Array& params, bool fHelp)
return ret;
}
+Value listwallets(CWallet* pWallet, const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 0)
+ throw runtime_error(
+ "listwallets\n"
+ "Returns list of wallets.");
+
+ Object obj;
+ BOOST_FOREACH(const wallet_map::value_type& item, pWalletMap->wallets)

I would prefer not to have to access pWalletMap->wallets directly...but using BOOST_FOREACH like this is quite convenient.

@sipa Owner
sipa added a note

You can implement an iterator for CWalletMap, if you really want BOOST_FOREACH.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/bitcoinrpc.cpp
((6 lines not shown))
try
{
// Execute
Value result;
{
- if (pcmd->unlocked)
- result = pcmd->actor(params, false);
+ LOCK(pWalletMap->cs_WalletMap);
@sipa Owner
sipa added a note

I don't think you want to keep the walletmap locked during the actual RPC execution.

Totally agreed - this was just me being extra cautious until the locking issues can be further looked into.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@sipa sipa commented on the diff
src/bitcoinrpc.cpp
@@ -1220,6 +1228,9 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "lockunspent" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "lockunspent" && n > 1) ConvertTo<Array>(params[1]);
if (strMethod == "importprivkey" && n > 2) ConvertTo<bool>(params[2]);
+ if (strMethod == "loadwallet" && n > 1) ConvertTo<bool>(params[1]);
+ if (strMethod == "loadwallet" && n > 2) ConvertTo<bool>(params[2]);
+ if (strMethod == "loadwallet" && n > 3) ConvertTo<boost::int64_t>(params[3]);
@sipa Owner
sipa added a note

Doesn't RPCConvertValues need some magic to deal with usewallet?

usewallet used to call RPCConvertValues on the parameters and pass it to CRPCTable::execute.

Now RPCConvertValues does the magic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/keystore.cpp
((6 lines not shown))
return true;
}
+void CCryptoKeyStore::SleepThenLock(int64 nMyWakeTime)
@sipa Owner
sipa added a note

What is this? Seems unrelated to the pull request...

The reason this was added was because we need to be able to unlock each wallet individually. The RPC methods shouldn't have to be keeping track of when it's time to lock the wallet again, so the options seem to be to either move the timer to within the CCryptoKeyStore class itself - or to write a helper class that manages this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/util.cpp
@@ -944,12 +944,31 @@ bool WildcardMatch(const string& str, const string& mask)
return WildcardMatch(str.c_str(), mask.c_str());
}
-
-
-
-
-
-
+vector<string> GetFilesAtPath(const boost::filesystem::path& _path, unsigned int flags)
+{
+ vector<string> vstrFiles;
+ if (!boost::filesystem::exists(_path))
+ throw runtime_error("Path does not exist.");
+
+ if ((flags & file_option_flags::REGULAR_FILES) && boost::filesystem::is_regular_file(_path))
+ {
+ vstrFiles.push_back(_path.filename().string());
@sipa Owner
sipa added a note

Just use _path.string().

Won't that return the complete path including directories? I just want the filenames.

@sipa Owner
sipa added a note

Oh, yes - you'll need compatibility with boost filesystem v2 though... for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/wallet.h
@@ -311,6 +313,31 @@ class CWallet : public CCryptoKeyStore
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
};
+/** A CWalletMap associates wallets with names and automatically deallocates them upon destruction.
+ */
+const boost::regex WALLET_NAME_REGEX("[a-zA-Z0-9_]*");
+const boost::regex WALLET_FILE_REGEX("wallet-([a-zA-Z0-9_]+)\\.dat");
+typedef std::map<std::string, CWallet*> wallet_map;
+class CWalletMap
+{
+public:
+ mutable CCriticalSection cs_WalletMap;
@sipa Owner
sipa added a note

Is there an actual need for this critsect to be exposed publically? Ideally (and I know a lot of old code offends against this horribly), critical sections are private and only taken by class methods itself.

so the preferred style would be something like a lock method containing LOCK(cs_WalletMap)? I guess that wouldn't work because it would go out of scope when the method returns.

So could you give a quick example of the style?

Actually, the only locking really needed is when unloading wallets. The rest of the wallet locking could be handled by the wallet class itself. So it seems an even better solution is to just lock on the wallet inside the UnloadWallet method. I'm wondering whether we should be locking on the UnregisterWallet method in main...Btw, is the std::map class thread-safe? Are inserts, deletes, and searches atomic?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@CodeShark CodeShark commented on the diff
src/makefile.unix
@@ -32,6 +32,7 @@ LIBS += \
-l boost_filesystem$(BOOST_LIB_SUFFIX) \
-l boost_program_options$(BOOST_LIB_SUFFIX) \
-l boost_thread$(BOOST_LIB_SUFFIX) \
+ -l boost_regex$(BOOST_LIB_SUFFIX) \

This is what's causing BitcoinPullTester to fail. Could we add this library?

@Diapolo
Diapolo added a note

Is Boost Regex a compiled lib or does it consist only of a .hpp file? If you need it for this pull to work you will also need to add it to bitcoin-qt.pro for the Qt client to work.

@gavinandresen Owner

If I recall correctly, boost::regex can be used either as headers-only OR requires-linking. Downside of headers-only is it increases compile times and uses a lot more memory when compiling.

It seems odd that the build testing machine would have boost built without the regex library, I thought the regexp library was built by default when you built boost.

@Diapolo indeed. I got this branch to build the Qt client on Mac OS 10.8. I'm still having some problems with std::basic_ostream and QtCore/qglobal.h when I use -mmacosx-version-min=10.5. Using -mmacosx-version-min=10.7 seems to make the first problem go away. The second problem is just a warning.

-mmacosx-version-min=10.6 even works. But 10.5, no way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@CodeShark

Hmm, still having some issues with the default wallet not unloading at shutdown. Will need to go over the shutdown sequence to make sure all threads relinquish their pointers to it.

@gavinandresen

Just to set expectations:

This big a change, in this critical a part of the codebase, will need:

  • A comprehensive test plan, that exercises all the things that have changed.
  • Testing by at least two different people who aren't developers, on Windows and either Linux or Mac

See https://github.com/bitcoin/QA for the lastest QA process.

@BitcoinPullTester

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/1c45edce2fbe76f7e146ee12c1df80c66c5fa8f9 for binaries and test log.

@BitcoinPullTester

Automatic sanity-testing: FAILED MERGE, see http://jenkins.bluematt.me/pull-tester/6c7f86ae371f955371fba05c7f747e4659cd39c8 for test log.

This pull does not merge cleanly onto current master
This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/
Contact BlueMatt on freenode if something looks broken.

@MrLei

How i can install bitcoind whit Dynamically Loadable Multiple Wallet ?

@gavinandresen

Rebase needed.

@Tranz5

This is awesome work. I hope it makes it way to BTC soon. I've been playing with it for a bit now. Here are the issues I am working through.
1) Export doesn't work. ( Tried making BitCoinGui exportAction public and referencing it in WalletView::gotoHistoryPage but that only gives me default wallet) Still working on different methods to fix this.
2) The RPC commands loadwallet and unloadwallet do not reflect in gui. I think the gui needs a connect to rpc commands.
3) When clicking on the transaction on the right side of the gui, the transaction button doesn't get focus.
4) The gui can't create a new wallet. using loadwallet then unloadwallet rcp, then load button in gui works, but..

So far these are the only issues I have found.

Thanks again for the hard work. I'll share what I can when as I work through these changes. I am still new and trying to catchup as quick as possible. Any hints are appreciated it.

Happy Bitcoining!

@Tranz5

I also found that sign message didn't work with other wallets.

I have found a solution to all of these.

I can do a pull request to this version, if this actually has a chance to be part of btc. I don't have time to rebase though.

Thanks!

@bananas2

Is it already implemented?

@laanwj
Owner

No, the pull request was not kept up to date. I needs a lot of rebasing to apply to 0.9.x, which Gavin already noted 5 months ago.

@laanwj
Owner

I'm going to close this. It has diverged too much from the current code base and no one seems to be interested in rebasing it.

In case anyone ever wants to have a shot at implementing multi-wallet I'll refer to to these code changes, as in principle they are good but they just arrived at the wrong time and were not kept in sync long enough to be tested properly and merged.

@laanwj laanwj closed this
@laanwj laanwj referenced this pull request
Closed

Multiple wallet #4093

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 24, 2012
  1. @CodeShark

    Added multiple wallet support

    CodeShark authored
    =============================
    
    A new global structure called pWalletMap has been added. Upon initialization, multiple wallets can be loaded.
    
    A new CWallet* parameter has been added to the RPC functions. Functions which do not use a wallet simply ignore it. In addition, a new field has been added to CRPCCommand that tells us whether or not the function uses a wallet.
    
    Two new RPC methods have been added:
      1) listwallets - Returns an array containing wallet names.
      2) usewallet - Prefix existing wallet RPC calls with usewallet <walletname> to use a particular wallet. If no wallet is specified, the default wallet is used.
        example: bitcoind usewallet foo listreceivedbyaddress 0 true
    
    TODO:
      1) Get wallet names from bitcoin.conf in init.cpp.
      2) Change help RPC so that the message does not depend on wallet state (i.e. walletpassphrase RPC call)
  2. @CodeShark
  3. @CodeShark
  4. @CodeShark

    Added loading of wallet names and files from -usewallet arguments

    CodeShark authored
    =================================================================
    
    You can now specify additional wallets in the config file or via command line arguments:
    
    	usewallet=foo
    
    or
    
    	bitcoind -usewallet=foo
    
    A default wallet called "default" in the RPC and using file "wallet.dat" is always loaded, as to not break compatibility with the master branch. Therefore, additional wallets should neither be called "default" nor "wallet" nor anything else that might conflict with other filenames in the .bitcoin directory.
    
    The wallet will be stored in a file called foo.dat. If the wallet doesn't yet exist, it will be created the first time bitcoind is run.
    
    TODO: Ensure filename collisions cannot occur. Perhaps allow the wallet files to be arbitrarily named rather than tied to their identifier.
  5. @CodeShark

    TxMemPool::accept() calls SyncWithWallets(), so all mempool transacti…

    CodeShark authored
    …ons are synched automatically without having to call SyncWithWallets() explicitly. This is important when sending between two wallets in a single bitcoind instance so that the receiving wallet is alerted of the transaction immediately.
    
    Removed calls to SyncWithWallets() in ProcessMessage() since SyncWithWallets() is already called by tx.AcceptToMemoryPool().
    
    SyncWithWallets() is still called explicitly from CBlock::ConnectBlock() since the transaction never goes through the mempool in this case.
  6. @CodeShark
  7. @CodeShark

    Removed dependency on wallet encryption state for getting help on RPC…

    CodeShark authored
    … methods. Help always returns usage info now.
  8. @CodeShark
Commits on Dec 25, 2012
  1. @CodeShark
  2. @CodeShark
Commits on Dec 26, 2012
  1. @CodeShark

    Moved wallet detail information out of getinfo and put it in listwall…

    CodeShark authored
    …ets. getinfo now just shows how many wallets are loaded.
  2. @CodeShark

    Moved code for locking a wallet automatically at a certain time from …

    CodeShark authored
    …rpcwallet.cpp into CCryptoKeyStore class.
    
    TODO:
      Encapsulate the thread spawning and make the call nonblocking.
      Give each thread a unique name.
Commits on Dec 27, 2012
  1. @CodeShark

    Dynamic loading and unloading of wallets.

    CodeShark authored
    New Changes:
      - Moved LoadWallet out of init.cpp and into CWalletMap class.
      - Added new RPC methods: loadwallet and unloadwallet.
    
    TODO:
      - Clean up I/O in CWalletMap::LoadWallet - debug, error, and UI output functions.
      - Make sure wallet loading and unloading are thread-safe.
      - Save wallets to bitcoin.conf automatically.
  2. @CodeShark

    New naming scheme for wallets. Checks for valid character set. CWalle…

    CodeShark authored
    …tMap now handles unregistration of wallets from main.
    
    Added linker option to makefiles for boost_regex.
  3. @CodeShark

    More load options at startup.

    CodeShark authored
    If at least one -usewallet parameter is given, it will use those parameters to determine which wallets to load at startup.
    If no -usewallet parameters are given, it searches the data directory for files named wallet-<walletname>.dat.
    
    Also added -nousewallet parameters which override either -usewallet or the data directory.
  4. @CodeShark

    Thread-safe CWalletMap.

    CodeShark authored
Commits on Dec 29, 2012
  1. @CodeShark
  2. @CodeShark
  3. @CodeShark
Commits on Jan 7, 2013
  1. @CodeShark
  2. @CodeShark

    Fixed usewallet params.

    CodeShark authored
Commits on Jan 10, 2013
  1. @CodeShark
  2. @CodeShark

    Better encapsulation on WalletMap class, moved critical section locks…

    CodeShark authored
    … to within the class methods themselves and out of bitcoinrpc.cpp, wallet unload locks on individual wallet rather than all wallets.
  3. @CodeShark
  4. @CodeShark
  5. @CodeShark

    Fixed test_bitcoin issue.

    CodeShark authored
  6. @CodeShark
  7. @CodeShark

    Added ReacceptWalletTransactions() registered wallet function in main…

    CodeShark authored
    … rather than iterating through the wallet map in init.
  8. @CodeShark
  9. @CodeShark
Commits on Jan 11, 2013
  1. @CodeShark
  2. @CodeShark
Commits on Jan 14, 2013
  1. @CodeShark

    Added Timer

    CodeShark authored
  2. @CodeShark
  3. @CodeShark
  4. @CodeShark
  5. @CodeShark
Commits on Jan 19, 2013
  1. @CodeShark
Something went wrong with that request. Please try again.