aboutsummaryrefslogtreecommitdiff
path: root/src/rpcwallet.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2013-05-07 10:47:00 -0400
committerGavin Andresen <gavinandresen@gmail.com>2013-05-07 11:47:33 -0400
commit92f2c1fe0fe2905540b0435188988851145f92be (patch)
treebd9d7b05aee0bbe4520ddcb08b0a88947c51795d /src/rpcwallet.cpp
parent9d053d170be718cf0ff902916fb11ffdee46537b (diff)
Use boost::asio::deadline_timer for walletpassphrase timeout
New method in bitcoinrpc: RunLater, that uses a map of deadline timers to run a function later. Behavior of walletpassphrase is changed; before, calling walletpassphrase again before the lock timeout passed would result in: Error: Wallet is already unlocked. You would have to call lockwallet before walletpassphrase. Now: the last walletpassphrase with correct password wins, and overrides any previous timeout. Fixes issue# 1961 which was caused by spawning too many threads. Test plan: Start with encrypted wallet, password 'foo' NOTE: python -c 'import time; print("%d"%time.time())' ... will tell you current unix timestamp. Try: walletpassphrase foo 600 getinfo EXPECT: unlocked_until is about 10 minutes in the future walletpassphrase foo 1 sleep 2 sendtoaddress mun74Bvba3B1PF2YkrF4NsgcJwHXXh12LF 11 EXPECT: Error: Please enter the wallet passphrase with walletpassphrase first. walletpassphrase foo 600 walletpassphrase foo 0 getinfo EXPECT: wallet is locked (unlocked_until is 0) walletpassphrase foo 10 walletpassphrase foo 600 getinfo EXPECT: wallet is unlocked until 10 minutes in future walletpassphrase foo 60 walletpassphrase bar 600 EXPECT: Error, incorrect passphrase getinfo EXPECT: wallet still scheduled to lock 60 seconds from first (successful) walletpassphrase
Diffstat (limited to 'src/rpcwallet.cpp')
-rw-r--r--src/rpcwallet.cpp67
1 files changed, 11 insertions, 56 deletions
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 5fd400c6bb..f304f70269 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -84,7 +84,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
if (pwalletMain->IsCrypted())
- obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
+ obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj;
}
@@ -1256,56 +1256,11 @@ Value keypoolrefill(const Array& params, bool fHelp)
}
-void ThreadTopUpKeyPool(void* parg)
+static void LockWallet(CWallet* pWallet)
{
- // Make this thread recognisable as the key-topping-up thread
- RenameThread("bitcoin-key-top");
-
- pwalletMain->TopUpKeyPool();
-}
-
-void ThreadCleanWalletPassphrase(void* parg)
-{
- // Make this thread recognisable as the wallet relocking thread
- RenameThread("bitcoin-lock-wa");
-
- int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
-
- ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
-
- if (nWalletUnlockTime == 0)
- {
- nWalletUnlockTime = nMyWakeTime;
-
- do
- {
- if (nWalletUnlockTime==0)
- break;
- int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
- if (nToSleep <= 0)
- break;
-
- LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
- MilliSleep(nToSleep);
- ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
-
- } while(1);
-
- if (nWalletUnlockTime)
- {
- nWalletUnlockTime = 0;
- pwalletMain->Lock();
- }
- }
- else
- {
- if (nWalletUnlockTime < nMyWakeTime)
- nWalletUnlockTime = nMyWakeTime;
- }
-
- LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
-
- delete (int64*)parg;
+ LOCK(cs_nWalletUnlockTime);
+ nWalletUnlockTime = 0;
+ pWallet->Lock();
}
Value walletpassphrase(const Array& params, bool fHelp)
@@ -1319,9 +1274,6 @@ Value walletpassphrase(const Array& params, bool fHelp)
if (!pwalletMain->IsCrypted())
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
- if (!pwalletMain->IsLocked())
- throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked.");
-
// Note that the walletpassphrase is stored in params[0] which is not mlock()ed
SecureString strWalletPass;
strWalletPass.reserve(100);
@@ -1339,9 +1291,12 @@ Value walletpassphrase(const Array& params, bool fHelp)
"walletpassphrase <passphrase> <timeout>\n"
"Stores the wallet decryption key in memory for <timeout> seconds.");
- NewThread(ThreadTopUpKeyPool, NULL);
- int64* pnSleepTime = new int64(params[1].get_int64());
- NewThread(ThreadCleanWalletPassphrase, pnSleepTime);
+ pwalletMain->TopUpKeyPool();
+
+ int64 nSleepTime = params[1].get_int64();
+ LOCK(cs_nWalletUnlockTime);
+ nWalletUnlockTime = GetTime() + nSleepTime;
+ RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
return Value::null;
}