You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1881 lines
61 KiB

// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "wallet.h"
#include "walletdb.h"
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
#include "crypter.h"
#include "ui_interface.h"
#include "base58.h"
#include <boost/algorithm/string/replace.hpp>
using namespace std;
//////////////////////////////////////////////////////////////////////////////
//
// mapWallet
//
struct CompareValueOnly
{
bool operator()(const pair<int64, pair<const CWalletTx*, unsigned int> >& t1,
const pair<int64, pair<const CWalletTx*, unsigned int> >& t2) const
{
return t1.first < t2.first;
}
};
CPubKey CWallet::GenerateNewKey()
{
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
RandAddSeedPerfmon();
CKey secret;
secret.MakeNewKey(fCompressed);
// Compressed public keys were introduced in version 0.6.0
if (fCompressed)
SetMinVersion(FEATURE_COMPRPUBKEY);
CPubKey pubkey = secret.GetPubKey();
if (!AddKeyPubKey(secret, pubkey))
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
return pubkey;
}
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
{
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false;
if (!fFileBacked)
return true;
if (!IsCrypted()) {
return CWalletDB(strWalletFile).WriteKey(pubkey, secret.GetPrivKey());
}
return true;
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
}
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
{
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
return false;
if (!fFileBacked)
return true;
{
LOCK(cs_wallet);
if (pwalletdbEncryption)
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
else
return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
}
return false;
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
}
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
}
bool CWallet::AddCScript(const CScript& redeemScript)
{
if (!CCryptoKeyStore::AddCScript(redeemScript))
return false;
if (!fFileBacked)
return true;
return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
}
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
{
CCrypter crypter;
CKeyingMaterial vMasterKey;
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
{
LOCK(cs_wallet);
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
{
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
continue; // try another master key
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
if (CCryptoKeyStore::Unlock(vMasterKey))
return true;
}
}
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
return false;
}
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
{
bool fWasLocked = IsLocked();
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
{
LOCK(cs_wallet);
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
Lock();
CCrypter crypter;
CKeyingMaterial vMasterKey;
BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
{
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
return false;
if (CCryptoKeyStore::Unlock(vMasterKey))
{
int64 nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
return false;
CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
if (fWasLocked)
Lock();
return true;
}
}
}
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
return false;
}
11 years ago
void CWallet::SetBestChain(const CBlockLocator& loc)
{
CWalletDB walletdb(strWalletFile);
walletdb.WriteBestBlock(loc);
}
// This class implements an addrIncoming entry that causes pre-0.4
// clients to crash on startup if reading a private-key-encrypted wallet.
class CCorruptAddress
{
public:
IMPLEMENT_SERIALIZE
(
if (nType & SER_DISK)
READWRITE(nVersion);
)
};
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
{
if (nWalletVersion >= nVersion)
return true;
// when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
if (fExplicit && nVersion > nWalletMaxVersion)
nVersion = FEATURE_LATEST;
nWalletVersion = nVersion;
if (nVersion > nWalletMaxVersion)
nWalletMaxVersion = nVersion;
if (fFileBacked)
{
CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
if (nWalletVersion >= 40000)
{
// Versions prior to 0.4.0 did not support the "minversion" record.
// Use a CCorruptAddress to make them crash instead.
CCorruptAddress corruptAddress;
pwalletdb->WriteSetting("addrIncoming", corruptAddress);
}
if (nWalletVersion > 40000)
pwalletdb->WriteMinVersion(nWalletVersion);
if (!pwalletdbIn)
delete pwalletdb;
}
return true;
}
bool CWallet::SetMaxVersion(int nVersion)
{
// cannot downgrade below current version
if (nWalletVersion > nVersion)
return false;
nWalletMaxVersion = nVersion;
return true;
}
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
{
if (IsCrypted())
return false;
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
CKeyingMaterial vMasterKey;
RandAddSeedPerfmon();
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
CMasterKey kMasterKey;
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
RandAddSeedPerfmon();
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
CCrypter crypter;
int64 nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
return false;
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
return false;
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
{
LOCK(cs_wallet);
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
if (fFileBacked)
{
pwalletdbEncryption = new CWalletDB(strWalletFile);
if (!pwalletdbEncryption->TxnBegin())
return false;
pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
}
if (!EncryptKeys(vMasterKey))
{
if (fFileBacked)
pwalletdbEncryption->TxnAbort();
exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
}
// Encryption was introduced in version 0.4.0
SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
if (fFileBacked)
{
if (!pwalletdbEncryption->TxnCommit())
exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
delete pwalletdbEncryption;
pwalletdbEncryption = NULL;
}
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
Lock();
Unlock(strWalletPassphrase);
NewKeyPool();
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
Lock();
// Need to completely rewrite the wallet file; if we don't, bdb might keep
// bits of the unencrypted private key in slack space in the database file.
CDB::Rewrite(strWalletFile);
}
NotifyStatusChanged(this);
11 years ago
Add wallet privkey encryption. This commit adds support for ckeys, or enCrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses. Keys are encrypted with AES-256-CBC using OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using SHA512 with (by default) 25000 rounds and a random salt. By default, the user's wallet remains unencrypted until they call the RPC command encryptwallet <passphrase> or, from the GUI menu, Options-> Encrypt Wallet. When the user is attempting to call RPC functions which require the password to unlock the wallet, an error will be returned unless they call walletpassphrase <passphrase> <time to keep key in memory> first. A keypoolrefill command has been added which tops up the users keypool (requiring the passphrase via walletpassphrase first). keypoolsize has been added to the output of getinfo to show the user the number of keys left before they need to specify their passphrase (and call keypoolrefill). Note that walletpassphrase will automatically fill keypool in a separate thread which it spawns when the passphrase is set. This could cause some delays in other threads waiting for locks on the wallet passphrase, including one which could cause the passphrase to be stored longer than expected, however it will not allow the passphrase to be used longer than expected as ThreadCleanWalletPassphrase will attempt to get a lock on the key as soon as the specified lock time has arrived. When the keypool runs out (and wallet is locked) GetOrReuseKeyFromPool returns vchDefaultKey, meaning miners may start to generate many blocks to vchDefaultKey instead of a new key each time. A walletpassphrasechange <oldpassphrase> <newpassphrase> has been added to allow the user to change their password via RPC. Whenever keying material (unencrypted private keys, the user's passphrase, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible. Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention. Thanks to jgarzik for the original patch and sipa, gmaxwell and many others for all their input. Conflicts: src/wallet.cpp
11 years ago
return true;
}
int64 CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
{
int64 nRet = nOrderPosNext++;
if (pwalletdb) {
pwalletdb->WriteOrderPosNext(nOrderPosNext);
} else {
CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
}
return nRet;
}
CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
{
CWalletDB walletdb(strWalletFile);
// First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
TxItems txOrdered;
// Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
// would make this much faster for applications that do this a lot.
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
CWalletTx* wtx = &((*it).second);
txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
}
acentries.clear();
walletdb.ListAccountCreditDebit(strAccount, acentries);
BOOST_FOREACH(CAccountingEntry& entry, acentries)
{
txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
}
return txOrdered;
}
void CWallet::WalletUpdateSpent(const CTransaction &tx)
{
// Anytime a signature is successfully verified, it's proof the outpoint is spent.
// Update the wallet spent flag if it doesn't know due to wallet.dat being
// restored from backup or the user making copies of wallet.dat.
{
LOCK(cs_wallet);
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
CWalletTx& wtx = (*mi).second;
if (txin.prevout.n >= wtx.vout.size())
printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
{
printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkSpent(txin.prevout.n);
wtx.WriteToDisk();
NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
}
}
}
}
}
void CWallet::MarkDirty()
{
{
LOCK(cs_wallet);
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
item.second.MarkDirty();
}
}
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
{
LOCK(cs_wallet);
// Inserts only if not already there, returns tx inserted or tx found
pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
CWalletTx& wtx = (*ret.first).second;
wtx.BindWallet(this);
bool fInsertedNew = ret.second;
if (fInsertedNew)
{
wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext();
wtx.nTimeSmart = wtx.nTimeReceived;
if (wtxIn.hashBlock != 0)
{
if (mapBlockIndex.count(wtxIn.hashBlock))
{
unsigned int latestNow = wtx.nTimeReceived;
unsigned int latestEntry = 0;
{
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
int64 latestTolerated = latestNow + 300;
std::list<CAccountingEntry> acentries;
TxItems txOrdered = OrderedTxItems(acentries);
for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx == &wtx)
continue;
CAccountingEntry *const pacentry = (*it).second.second;
int64 nSmartTime;
if (pwtx)
{
nSmartTime = pwtx->nTimeSmart;
if (!nSmartTime)
nSmartTime = pwtx->nTimeReceived;
}
else
nSmartTime = pacentry->nTime;
if (nSmartTime <= latestTolerated)
{
latestEntry = nSmartTime;
if (nSmartTime > latestNow)
latestNow = nSmartTime;
break;
}
}
}
unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime;
wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
}
else
printf("AddToWallet() : found %s in block %s not in index\n",
wtxIn.GetHash().ToString().c_str(),
wtxIn.hashBlock.ToString().c_str());
}
}
bool fUpdated = false;
if (!fInsertedNew)
{
// Merge
if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
{
wtx.hashBlock = wtxIn.hashBlock;
fUpdated = true;
}
if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
{
wtx.vMerkleBranch = wtxIn.vMerkleBranch;
wtx.nIndex = wtxIn.nIndex;
fUpdated = true;
}
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
{
wtx.fFromMe = wtxIn.fFromMe;
fUpdated = true;
}
fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
}
//// debug print
printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
// Write to disk
if (fInsertedNew || fUpdated)
if (!wtx.WriteToDisk())
return false;
if (!fHaveGUI) {
// If default receiving address gets used, replace it with a new one
if (vchDefaultKey.IsValid()) {
CScript scriptDefaultKey;
scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
if (txout.scriptPubKey == scriptDefaultKey)
{
CPubKey newDefaultKey;
if (GetKeyFromPool(newDefaultKey, false))
{
SetDefaultKey(newDefaultKey);
SetAddressBookName(vchDefaultKey.GetID(), "");
}
}
}
}
}
// since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
WalletUpdateSpent(wtx);
// Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
// notify an external script when a wallet transaction comes in or is updated
std::string strCmd = GetArg("-walletnotify", "");
if ( !strCmd.empty())
{
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free
}
}
return true;
}
// Add a transaction to the wallet, or update it.
// pblock is optional, but should be provided if the transaction is known to be in a block.
// If fUpdate is true, existing transactions will be updated.
bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
{
{
LOCK(cs_wallet);
bool fExisted = mapWallet.count(hash);
if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx) || IsFromMe(tx))
{
CWalletTx wtx(this,tx);
// Get merkle branch if transaction was found in a block
if (pblock)
wtx.SetMerkleBranch(pblock);
return AddToWallet(wtx);
}
else
WalletUpdateSpent(tx);
}
return false;
}
bool CWallet::EraseFromWallet(uint256 hash)
{
if (!fFileBacked)
return false;
{
LOCK(cs_wallet);
if (mapWallet.erase(hash))
CWalletDB(strWalletFile).EraseTx(hash);
}
return true;
}
bool CWallet::IsMine(const CTxIn &txin) const
{
{
LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
if (txin.prevout.n < prev.vout.size())
if (IsMine(prev.vout[txin.prevout.n]))
return true;
}
}
return false;
}
int64 CWallet::GetDebit(const CTxIn &txin) const
{
{
LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
if (txin.prevout.n < prev.vout.size())
if (IsMine(prev.vout[txin.prevout.n]))
return prev.vout[txin.prevout.n].nValue;
}
}
return 0;
}
bool CWallet::IsChange(const CTxOut& txout) const
{
CTxDestination address;
// TODO: fix handling of 'change' outputs. The assumption is that any
// payment to a TX_PUBKEYHASH that is mine but isn't in the address book
// is change. That assumption is likely to break when we implement multisignature
// wallets that return change back into a multi-signature-protected address;
// a better way of identifying which outputs are 'the send' and which are
// 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change).
if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
{
LOCK(cs_wallet);
if (!mapAddressBook.count(address))
return true;
}
return false;
}
int64 CWalletTx::GetTxTime() const
{
int64 n = nTimeSmart;
return n ? n : nTimeReceived;
}
int CWalletTx::GetRequestCount() const
{
// Returns -1 if it wasn't being tracked
int nRequests = -1;
{
LOCK(pwallet->cs_wallet);
if (IsCoinBase())
{
// Generated block
if (hashBlock != 0)
{
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
if (mi != pwallet->mapRequestCount.end())
nRequests = (*mi).second;
}
}
else
{
// Did anyone request this transaction?
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
if (mi != pwallet->mapRequestCount.end())
{
nRequests = (*mi).second;
// How about the block it's in?
if (nRequests == 0 && hashBlock != 0)
{
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
if (mi != pwallet->mapRequestCount.end())
nRequests = (*mi).second;
else
nRequests = 1; // If it's in someone else's block it must have got out
}
}
}
}
return nRequests;
}