Browse Source

[rpcwallet] Clamp walletpassphrase value at 100M seconds

Larger values seem to trigger a bug on macos+libevent (resulting in the
rpc server stopping).

Github-Pull: #12905
Rebased-From: 662d19ff7217d0e6c7975ca311933f640955a53e
0.16
Suhas Daftuar 7 years ago committed by MarcoFalke
parent
commit
cfc6f7413b
  1. 10
      src/wallet/rpcwallet.cpp
  2. 9
      test/functional/wallet_encryption.py

10
src/wallet/rpcwallet.cpp

@ -2322,8 +2322,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
"This is needed prior to performing transactions related to private keys such as sending bitcoins\n" "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"passphrase\" (string, required) The wallet passphrase\n" "1. \"passphrase\" (string, required) The wallet passphrase\n"
"2. timeout (numeric, required) The time to keep the decryption key in seconds. Limited to at most 1073741824 (2^30) seconds.\n" "2. timeout (numeric, required) The time to keep the decryption key in seconds; capped at 100000000 (~3 years).\n"
" Any value greater than 1073741824 seconds will be set to 1073741824 seconds.\n"
"\nNote:\n" "\nNote:\n"
"Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n" "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
"time that overrides the old one.\n" "time that overrides the old one.\n"
@ -2358,9 +2357,10 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
if (nSleepTime < 0) { if (nSleepTime < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative."); throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
} }
// Clamp timeout to 2^30 seconds // Clamp timeout
if (nSleepTime > (int64_t)1 << 30) { constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
nSleepTime = (int64_t)1 << 30; if (nSleepTime > MAX_SLEEP_TIME) {
nSleepTime = MAX_SLEEP_TIME;
} }
if (strWalletPass.length() > 0) if (strWalletPass.length() > 0)

9
test/functional/wallet_encryption.py

@ -64,14 +64,15 @@ class WalletEncryptionTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "Timeout cannot be negative.", self.nodes[0].walletpassphrase, passphrase2, -10) assert_raises_rpc_error(-8, "Timeout cannot be negative.", self.nodes[0].walletpassphrase, passphrase2, -10)
# Check the timeout # Check the timeout
# Check a time less than the limit # Check a time less than the limit
expected_time = int(time.time()) + (1 << 30) - 600 MAX_VALUE = 100000000
self.nodes[0].walletpassphrase(passphrase2, (1 << 30) - 600) expected_time = int(time.time()) + MAX_VALUE - 600
self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE - 600)
actual_time = self.nodes[0].getwalletinfo()['unlocked_until'] actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
assert_greater_than_or_equal(actual_time, expected_time) assert_greater_than_or_equal(actual_time, expected_time)
assert_greater_than(expected_time + 5, actual_time) # 5 second buffer assert_greater_than(expected_time + 5, actual_time) # 5 second buffer
# Check a time greater than the limit # Check a time greater than the limit
expected_time = int(time.time()) + (1 << 30) - 1 expected_time = int(time.time()) + MAX_VALUE - 1
self.nodes[0].walletpassphrase(passphrase2, (1 << 33)) self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE + 1000)
actual_time = self.nodes[0].getwalletinfo()['unlocked_until'] actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
assert_greater_than_or_equal(actual_time, expected_time) assert_greater_than_or_equal(actual_time, expected_time)
assert_greater_than(expected_time + 5, actual_time) # 5 second buffer assert_greater_than(expected_time + 5, actual_time) # 5 second buffer

Loading…
Cancel
Save