mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-02-02 09:54:29 +00:00
Merge pull request #480 from gavinandresen/deadlocks
Simplify mutex locking, fix deadlocks. Fixes issue #453
This commit is contained in:
commit
cb6c4b883d
@ -39,3 +39,47 @@ v vector or similar list objects
|
|||||||
map map or multimap
|
map map or multimap
|
||||||
set set or multiset
|
set set or multiset
|
||||||
bn CBigNum
|
bn CBigNum
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
Locking/mutex usage notes
|
||||||
|
|
||||||
|
The code is multi-threaded, and uses mutexes and the CRITICAL_BLOCK/TRY_CRITICAL_BLOCK macros to protect data structures.
|
||||||
|
|
||||||
|
Deadlocks due to inconsistent lock ordering (thread 1 locks cs_main and then cs_wallet, while thread 2 locks them in the opposite order: result, deadlock as each waits for the other to release its lock) are a problem. Compile with -DDEBUG_LOCKORDER to get lock order inconsistencies reported in the debug.log file.
|
||||||
|
|
||||||
|
Re-architecting the core code so there are better-defined interfaces between the various components is a goal, with any necessary locking done by the components (e.g. see the self-contained CKeyStore class and its cs_KeyStore lock for example).
|
||||||
|
|
||||||
|
-------
|
||||||
|
Threads
|
||||||
|
|
||||||
|
StartNode : Starts other threads.
|
||||||
|
|
||||||
|
ThreadGetMyExternalIP : Determines outside-the-firewall IP address, sends addr message to connected peers when it determines it.
|
||||||
|
|
||||||
|
ThreadIRCSeed : Joins IRC bootstrapping channel, watching for new peers and advertising this node's IP address.
|
||||||
|
|
||||||
|
ThreadSocketHandler : Sends/Receives data from peers on port 8333.
|
||||||
|
|
||||||
|
ThreadMessageHandler : Higher-level message handling (sending and receiving).
|
||||||
|
|
||||||
|
ThreadOpenConnections : Initiates new connections to peers.
|
||||||
|
|
||||||
|
ThreadTopUpKeyPool : replenishes the keystore's keypool.
|
||||||
|
|
||||||
|
ThreadCleanWalletPassphrase : re-locks an encrypted wallet after user has unlocked it for a period of time.
|
||||||
|
|
||||||
|
SendingDialogStartTransfer : used by pay-via-ip-address code (obsolete)
|
||||||
|
|
||||||
|
ThreadDelayedRepaint : repaint the gui
|
||||||
|
|
||||||
|
ThreadFlushWalletDB : Close the wallet.dat file if it hasn't been used in 500ms.
|
||||||
|
|
||||||
|
ThreadRPCServer : Remote procedure call handler, listens on port 8332 for connections and services them.
|
||||||
|
|
||||||
|
ThreadBitcoinMiner : Generates bitcoins
|
||||||
|
|
||||||
|
ThreadMapPort : Universal plug-and-play startup/shutdown
|
||||||
|
|
||||||
|
Shutdown : Does an orderly shutdown of everything
|
||||||
|
|
||||||
|
ExitTimeout : Windows-only, sleeps 5 seconds then exits application
|
||||||
|
@ -683,8 +683,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
||||||
CRITICAL_BLOCK(pwallet->cs_mapWallet)
|
CRITICAL_BLOCK(pwallet->cs_wallet)
|
||||||
CRITICAL_BLOCK(pwallet->cs_KeyStore)
|
|
||||||
{
|
{
|
||||||
// Get cursor
|
// Get cursor
|
||||||
Dbc* pcursor = GetCursor();
|
Dbc* pcursor = GetCursor();
|
||||||
|
@ -45,7 +45,7 @@ std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey()
|
|||||||
|
|
||||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
{
|
{
|
||||||
if (!SetCrypted())
|
if (!SetCrypted())
|
||||||
return false;
|
return false;
|
||||||
@ -72,7 +72,6 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
|||||||
bool CCryptoKeyStore::AddKey(const CKey& key)
|
bool CCryptoKeyStore::AddKey(const CKey& key)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_KeyStore)
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
|
||||||
{
|
{
|
||||||
if (!IsCrypted())
|
if (!IsCrypted())
|
||||||
return CBasicKeyStore::AddKey(key);
|
return CBasicKeyStore::AddKey(key);
|
||||||
@ -106,7 +105,7 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey,
|
|||||||
|
|
||||||
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
{
|
{
|
||||||
if (!IsCrypted())
|
if (!IsCrypted())
|
||||||
return CBasicKeyStore::GetKey(address, keyOut);
|
return CBasicKeyStore::GetKey(address, keyOut);
|
||||||
@ -128,7 +127,7 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
|||||||
|
|
||||||
bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
|
bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
{
|
{
|
||||||
if (!IsCrypted())
|
if (!IsCrypted())
|
||||||
return CKeyStore::GetPubKey(address, vchPubKeyOut);
|
return CKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||||
@ -146,7 +145,6 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsi
|
|||||||
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_KeyStore)
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
|
||||||
{
|
{
|
||||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||||
return false;
|
return false;
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
|
|
||||||
class CKeyStore
|
class CKeyStore
|
||||||
{
|
{
|
||||||
public:
|
protected:
|
||||||
mutable CCriticalSection cs_KeyStore;
|
mutable CCriticalSection cs_KeyStore;
|
||||||
|
|
||||||
|
public:
|
||||||
virtual bool AddKey(const CKey& key) =0;
|
virtual bool AddKey(const CKey& key) =0;
|
||||||
virtual bool HaveKey(const CBitcoinAddress &address) const =0;
|
virtual bool HaveKey(const CBitcoinAddress &address) const =0;
|
||||||
virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0;
|
virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0;
|
||||||
@ -30,15 +31,21 @@ public:
|
|||||||
bool AddKey(const CKey& key);
|
bool AddKey(const CKey& key);
|
||||||
bool HaveKey(const CBitcoinAddress &address) const
|
bool HaveKey(const CBitcoinAddress &address) const
|
||||||
{
|
{
|
||||||
return (mapKeys.count(address) > 0);
|
bool result;
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
|
result = (mapKeys.count(address) > 0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||||
{
|
{
|
||||||
KeyMap::const_iterator mi = mapKeys.find(address);
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
if (mi != mapKeys.end())
|
|
||||||
{
|
{
|
||||||
keyOut.SetSecret((*mi).second);
|
KeyMap::const_iterator mi = mapKeys.find(address);
|
||||||
return true;
|
if (mi != mapKeys.end())
|
||||||
|
{
|
||||||
|
keyOut.SetSecret((*mi).second);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -74,8 +81,6 @@ protected:
|
|||||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
|
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mutable CCriticalSection cs_vMasterKey; //No guarantees master key wont get locked before you can use it, so lock this first
|
|
||||||
|
|
||||||
CCryptoKeyStore() : fUseCrypto(false)
|
CCryptoKeyStore() : fUseCrypto(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -89,18 +94,20 @@ public:
|
|||||||
{
|
{
|
||||||
if (!IsCrypted())
|
if (!IsCrypted())
|
||||||
return false;
|
return false;
|
||||||
return vMasterKey.empty();
|
bool result;
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
|
result = vMasterKey.empty();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lock()
|
bool Lock()
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
if (!SetCrypted())
|
||||||
{
|
return false;
|
||||||
if (!SetCrypted())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
vMasterKey.clear();
|
vMasterKey.clear();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,9 +116,12 @@ public:
|
|||||||
bool AddKey(const CKey& key);
|
bool AddKey(const CKey& key);
|
||||||
bool HaveKey(const CBitcoinAddress &address) const
|
bool HaveKey(const CBitcoinAddress &address) const
|
||||||
{
|
{
|
||||||
if (!IsCrypted())
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
return CBasicKeyStore::HaveKey(address);
|
{
|
||||||
return mapCryptedKeys.count(address) > 0;
|
if (!IsCrypted())
|
||||||
|
return CBasicKeyStore::HaveKey(address);
|
||||||
|
return mapCryptedKeys.count(address) > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const;
|
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const;
|
||||||
bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
|
bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
|
||||||
|
@ -2879,7 +2879,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
|
|||||||
reservekey.KeepKey();
|
reservekey.KeepKey();
|
||||||
|
|
||||||
// Track how many getdata requests this block gets
|
// Track how many getdata requests this block gets
|
||||||
CRITICAL_BLOCK(wallet.cs_mapRequestCount)
|
CRITICAL_BLOCK(wallet.cs_wallet)
|
||||||
wallet.mapRequestCount[pblock->GetHash()] = 0;
|
wallet.mapRequestCount[pblock->GetHash()] = 0;
|
||||||
|
|
||||||
// Process this block the same as if we had received it from another node
|
// Process this block the same as if we had received it from another node
|
||||||
|
625
src/rpc.cpp
625
src/rpc.cpp
@ -346,55 +346,50 @@ Value getnewaddress(const Array& params, bool fHelp)
|
|||||||
CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool());
|
CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool());
|
||||||
|
|
||||||
// This could be done in the same main CS as GetKeyFromKeyPool.
|
// This could be done in the same main CS as GetKeyFromKeyPool.
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
pwalletMain->SetAddressBookName(address, strAccount);
|
||||||
pwalletMain->SetAddressBookName(address, strAccount);
|
|
||||||
|
|
||||||
return address.ToString();
|
return address.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// requires cs_main, cs_mapWallet, cs_mapAddressBook locks
|
|
||||||
CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
|
CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
|
||||||
{
|
{
|
||||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||||
|
|
||||||
CAccount account;
|
CAccount account;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
walletdb.ReadAccount(strAccount, account);
|
||||||
|
|
||||||
|
bool bKeyUsed = false;
|
||||||
|
|
||||||
|
// Check if the current key has been used
|
||||||
|
if (!account.vchPubKey.empty())
|
||||||
{
|
{
|
||||||
walletdb.ReadAccount(strAccount, account);
|
CScript scriptPubKey;
|
||||||
|
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
|
||||||
bool bKeyUsed = false;
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
|
||||||
|
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
|
||||||
// Check if the current key has been used
|
++it)
|
||||||
if (!account.vchPubKey.empty())
|
|
||||||
{
|
{
|
||||||
CScript scriptPubKey;
|
const CWalletTx& wtx = (*it).second;
|
||||||
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
|
if (txout.scriptPubKey == scriptPubKey)
|
||||||
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
|
bKeyUsed = true;
|
||||||
++it)
|
|
||||||
{
|
|
||||||
const CWalletTx& wtx = (*it).second;
|
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
|
||||||
if (txout.scriptPubKey == scriptPubKey)
|
|
||||||
bKeyUsed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a new key
|
// Generate a new key
|
||||||
if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
|
if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
|
||||||
|
{
|
||||||
|
if (pwalletMain->GetKeyPoolSize() < 1)
|
||||||
{
|
{
|
||||||
if (pwalletMain->GetKeyPoolSize() < 1)
|
if (bKeyUsed || bForceNew)
|
||||||
{
|
throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
|
||||||
if (bKeyUsed || bForceNew)
|
}
|
||||||
throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
|
else
|
||||||
}
|
{
|
||||||
else
|
account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
|
||||||
{
|
pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
|
||||||
account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
|
walletdb.WriteAccount(strAccount, account);
|
||||||
pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
|
|
||||||
walletdb.WriteAccount(strAccount, account);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,12 +408,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
Value ret;
|
Value ret;
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
ret = GetAccountAddress(strAccount).ToString();
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
|
||||||
{
|
|
||||||
ret = GetAccountAddress(strAccount).ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -442,20 +432,15 @@ Value setaccount(const Array& params, bool fHelp)
|
|||||||
strAccount = AccountFromValue(params[1]);
|
strAccount = AccountFromValue(params[1]);
|
||||||
|
|
||||||
// Detect when changing the account of an address that is the 'unused current key' of another account:
|
// Detect when changing the account of an address that is the 'unused current key' of another account:
|
||||||
CRITICAL_BLOCK(cs_main)
|
if (pwalletMain->mapAddressBook.count(address))
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
|
||||||
{
|
{
|
||||||
if (pwalletMain->mapAddressBook.count(address))
|
string strOldAccount = pwalletMain->mapAddressBook[address];
|
||||||
{
|
if (address == GetAccountAddress(strOldAccount))
|
||||||
string strOldAccount = pwalletMain->mapAddressBook[address];
|
GetAccountAddress(strOldAccount, true);
|
||||||
if (address == GetAccountAddress(strOldAccount))
|
|
||||||
GetAccountAddress(strOldAccount, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
pwalletMain->SetAddressBookName(address, strAccount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pwalletMain->SetAddressBookName(address, strAccount);
|
||||||
|
|
||||||
return Value::null;
|
return Value::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,12 +457,9 @@ Value getaccount(const Array& params, bool fHelp)
|
|||||||
throw JSONRPCError(-5, "Invalid bitcoin address");
|
throw JSONRPCError(-5, "Invalid bitcoin address");
|
||||||
|
|
||||||
string strAccount;
|
string strAccount;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
|
||||||
{
|
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
|
||||||
map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
|
strAccount = (*mi).second;
|
||||||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
|
|
||||||
strAccount = (*mi).second;
|
|
||||||
}
|
|
||||||
return strAccount;
|
return strAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,15 +475,12 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
// Find all addresses that have the given account
|
// Find all addresses that have the given account
|
||||||
Array ret;
|
Array ret;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
const CBitcoinAddress& address = item.first;
|
||||||
{
|
const string& strName = item.second;
|
||||||
const CBitcoinAddress& address = item.first;
|
if (strName == strAccount)
|
||||||
const string& strName = item.second;
|
ret.push_back(address.ToString());
|
||||||
if (strName == strAccount)
|
|
||||||
ret.push_back(address.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -548,16 +527,12 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
|||||||
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
|
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
|
||||||
wtx.mapValue["to"] = params[3].get_str();
|
wtx.mapValue["to"] = params[3].get_str();
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
if (pwalletMain->IsLocked())
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
||||||
{
|
|
||||||
if(pwalletMain->IsLocked())
|
|
||||||
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
|
||||||
|
|
||||||
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
|
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
|
||||||
if (strError != "")
|
if (strError != "")
|
||||||
throw JSONRPCError(-4, strError);
|
throw JSONRPCError(-4, strError);
|
||||||
}
|
|
||||||
|
|
||||||
return wtx.GetHash().GetHex();
|
return wtx.GetHash().GetHex();
|
||||||
}
|
}
|
||||||
@ -586,19 +561,16 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
// Tally
|
// Tally
|
||||||
int64 nAmount = 0;
|
int64 nAmount = 0;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
const CWalletTx& wtx = (*it).second;
|
||||||
{
|
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
||||||
const CWalletTx& wtx = (*it).second;
|
continue;
|
||||||
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
if (txout.scriptPubKey == scriptPubKey)
|
if (txout.scriptPubKey == scriptPubKey)
|
||||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||||
nAmount += txout.nValue;
|
nAmount += txout.nValue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValueFromAmount(nAmount);
|
return ValueFromAmount(nAmount);
|
||||||
@ -607,15 +579,12 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
|
void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
const CBitcoinAddress& address = item.first;
|
||||||
{
|
const string& strName = item.second;
|
||||||
const CBitcoinAddress& address = item.first;
|
if (strName == strAccount)
|
||||||
const string& strName = item.second;
|
setAddress.insert(address);
|
||||||
if (strName == strAccount)
|
|
||||||
setAddress.insert(address);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,21 +608,18 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
// Tally
|
// Tally
|
||||||
int64 nAmount = 0;
|
int64 nAmount = 0;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
const CWalletTx& wtx = (*it).second;
|
||||||
{
|
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
||||||
const CWalletTx& wtx = (*it).second;
|
continue;
|
||||||
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
{
|
{
|
||||||
CBitcoinAddress address;
|
CBitcoinAddress address;
|
||||||
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
|
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
|
||||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||||
nAmount += txout.nValue;
|
nAmount += txout.nValue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,27 +630,25 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
|||||||
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
|
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
|
||||||
{
|
{
|
||||||
int64 nBalance = 0;
|
int64 nBalance = 0;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
|
||||||
|
// Tally wallet transactions
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
// Tally wallet transactions
|
const CWalletTx& wtx = (*it).second;
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
if (!wtx.IsFinal())
|
||||||
{
|
continue;
|
||||||
const CWalletTx& wtx = (*it).second;
|
|
||||||
if (!wtx.IsFinal())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int64 nGenerated, nReceived, nSent, nFee;
|
int64 nGenerated, nReceived, nSent, nFee;
|
||||||
wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
|
wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
|
||||||
|
|
||||||
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||||
nBalance += nReceived;
|
nBalance += nReceived;
|
||||||
nBalance += nGenerated - nSent - nFee;
|
nBalance += nGenerated - nSent - nFee;
|
||||||
}
|
|
||||||
|
|
||||||
// Tally internal accounting entries
|
|
||||||
nBalance += walletdb.GetAccountCreditDebit(strAccount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tally internal accounting entries
|
||||||
|
nBalance += walletdb.GetAccountCreditDebit(strAccount);
|
||||||
|
|
||||||
return nBalance;
|
return nBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,33 +727,31 @@ Value movecmd(const Array& params, bool fHelp)
|
|||||||
if (params.size() > 4)
|
if (params.size() > 4)
|
||||||
strComment = params[4].get_str();
|
strComment = params[4].get_str();
|
||||||
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||||
{
|
walletdb.TxnBegin();
|
||||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
|
||||||
walletdb.TxnBegin();
|
|
||||||
|
|
||||||
int64 nNow = GetAdjustedTime();
|
int64 nNow = GetAdjustedTime();
|
||||||
|
|
||||||
// Debit
|
// Debit
|
||||||
CAccountingEntry debit;
|
CAccountingEntry debit;
|
||||||
debit.strAccount = strFrom;
|
debit.strAccount = strFrom;
|
||||||
debit.nCreditDebit = -nAmount;
|
debit.nCreditDebit = -nAmount;
|
||||||
debit.nTime = nNow;
|
debit.nTime = nNow;
|
||||||
debit.strOtherAccount = strTo;
|
debit.strOtherAccount = strTo;
|
||||||
debit.strComment = strComment;
|
debit.strComment = strComment;
|
||||||
walletdb.WriteAccountingEntry(debit);
|
walletdb.WriteAccountingEntry(debit);
|
||||||
|
|
||||||
// Credit
|
// Credit
|
||||||
CAccountingEntry credit;
|
CAccountingEntry credit;
|
||||||
credit.strAccount = strTo;
|
credit.strAccount = strTo;
|
||||||
credit.nCreditDebit = nAmount;
|
credit.nCreditDebit = nAmount;
|
||||||
credit.nTime = nNow;
|
credit.nTime = nNow;
|
||||||
credit.strOtherAccount = strFrom;
|
credit.strOtherAccount = strFrom;
|
||||||
credit.strComment = strComment;
|
credit.strComment = strComment;
|
||||||
walletdb.WriteAccountingEntry(credit);
|
walletdb.WriteAccountingEntry(credit);
|
||||||
|
|
||||||
|
walletdb.TxnCommit();
|
||||||
|
|
||||||
walletdb.TxnCommit();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,23 +784,18 @@ Value sendfrom(const Array& params, bool fHelp)
|
|||||||
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
|
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
|
||||||
wtx.mapValue["to"] = params[5].get_str();
|
wtx.mapValue["to"] = params[5].get_str();
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
if (pwalletMain->IsLocked())
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
|
||||||
{
|
|
||||||
if(pwalletMain->IsLocked())
|
|
||||||
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
|
||||||
|
|
||||||
// Check funds
|
// Check funds
|
||||||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
||||||
if (nAmount > nBalance)
|
if (nAmount > nBalance)
|
||||||
throw JSONRPCError(-6, "Account has insufficient funds");
|
throw JSONRPCError(-6, "Account has insufficient funds");
|
||||||
|
|
||||||
// Send
|
// Send
|
||||||
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
|
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
|
||||||
if (strError != "")
|
if (strError != "")
|
||||||
throw JSONRPCError(-4, strError);
|
throw JSONRPCError(-4, strError);
|
||||||
}
|
|
||||||
|
|
||||||
return wtx.GetHash().GetHex();
|
return wtx.GetHash().GetHex();
|
||||||
}
|
}
|
||||||
@ -889,31 +846,26 @@ Value sendmany(const Array& params, bool fHelp)
|
|||||||
vecSend.push_back(make_pair(scriptPubKey, nAmount));
|
vecSend.push_back(make_pair(scriptPubKey, nAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
if (pwalletMain->IsLocked())
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
|
||||||
|
// Check funds
|
||||||
|
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
||||||
|
if (totalAmount > nBalance)
|
||||||
|
throw JSONRPCError(-6, "Account has insufficient funds");
|
||||||
|
|
||||||
|
// Send
|
||||||
|
CReserveKey keyChange(pwalletMain);
|
||||||
|
int64 nFeeRequired = 0;
|
||||||
|
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
|
||||||
|
if (!fCreated)
|
||||||
{
|
{
|
||||||
if(pwalletMain->IsLocked())
|
if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
|
||||||
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
throw JSONRPCError(-6, "Insufficient funds");
|
||||||
|
throw JSONRPCError(-4, "Transaction creation failed");
|
||||||
// Check funds
|
|
||||||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
|
||||||
if (totalAmount > nBalance)
|
|
||||||
throw JSONRPCError(-6, "Account has insufficient funds");
|
|
||||||
|
|
||||||
// Send
|
|
||||||
CReserveKey keyChange(pwalletMain);
|
|
||||||
int64 nFeeRequired = 0;
|
|
||||||
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
|
|
||||||
if (!fCreated)
|
|
||||||
{
|
|
||||||
if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
|
|
||||||
throw JSONRPCError(-6, "Insufficient funds");
|
|
||||||
throw JSONRPCError(-4, "Transaction creation failed");
|
|
||||||
}
|
|
||||||
if (!pwalletMain->CommitTransaction(wtx, keyChange))
|
|
||||||
throw JSONRPCError(-4, "Transaction commit failed");
|
|
||||||
}
|
}
|
||||||
|
if (!pwalletMain->CommitTransaction(wtx, keyChange))
|
||||||
|
throw JSONRPCError(-4, "Transaction commit failed");
|
||||||
|
|
||||||
return wtx.GetHash().GetHex();
|
return wtx.GetHash().GetHex();
|
||||||
}
|
}
|
||||||
@ -944,68 +896,62 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
|||||||
|
|
||||||
// Tally
|
// Tally
|
||||||
map<CBitcoinAddress, tallyitem> mapTally;
|
map<CBitcoinAddress, tallyitem> mapTally;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int nDepth = wtx.GetDepthInMainChain();
|
||||||
|
if (nDepth < nMinDepth)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = (*it).second;
|
CBitcoinAddress address;
|
||||||
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int nDepth = wtx.GetDepthInMainChain();
|
tallyitem& item = mapTally[address];
|
||||||
if (nDepth < nMinDepth)
|
item.nAmount += txout.nValue;
|
||||||
continue;
|
item.nConf = min(item.nConf, nDepth);
|
||||||
|
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
|
||||||
{
|
|
||||||
CBitcoinAddress address;
|
|
||||||
if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
tallyitem& item = mapTally[address];
|
|
||||||
item.nAmount += txout.nValue;
|
|
||||||
item.nConf = min(item.nConf, nDepth);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reply
|
// Reply
|
||||||
Array ret;
|
Array ret;
|
||||||
map<string, tallyitem> mapAccountTally;
|
map<string, tallyitem> mapAccountTally;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
const CBitcoinAddress& address = item.first;
|
||||||
|
const string& strAccount = item.second;
|
||||||
|
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
|
||||||
|
if (it == mapTally.end() && !fIncludeEmpty)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int64 nAmount = 0;
|
||||||
|
int nConf = INT_MAX;
|
||||||
|
if (it != mapTally.end())
|
||||||
{
|
{
|
||||||
const CBitcoinAddress& address = item.first;
|
nAmount = (*it).second.nAmount;
|
||||||
const string& strAccount = item.second;
|
nConf = (*it).second.nConf;
|
||||||
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
|
}
|
||||||
if (it == mapTally.end() && !fIncludeEmpty)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int64 nAmount = 0;
|
if (fByAccounts)
|
||||||
int nConf = INT_MAX;
|
{
|
||||||
if (it != mapTally.end())
|
tallyitem& item = mapAccountTally[strAccount];
|
||||||
{
|
item.nAmount += nAmount;
|
||||||
nAmount = (*it).second.nAmount;
|
item.nConf = min(item.nConf, nConf);
|
||||||
nConf = (*it).second.nConf;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
if (fByAccounts)
|
Object obj;
|
||||||
{
|
obj.push_back(Pair("address", address.ToString()));
|
||||||
tallyitem& item = mapAccountTally[strAccount];
|
obj.push_back(Pair("account", strAccount));
|
||||||
item.nAmount += nAmount;
|
obj.push_back(Pair("label", strAccount)); // deprecated
|
||||||
item.nConf = min(item.nConf, nConf);
|
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
|
||||||
}
|
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
|
||||||
else
|
ret.push_back(obj);
|
||||||
{
|
|
||||||
Object obj;
|
|
||||||
obj.push_back(Pair("address", address.ToString()));
|
|
||||||
obj.push_back(Pair("account", strAccount));
|
|
||||||
obj.push_back(Pair("label", strAccount)); // deprecated
|
|
||||||
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
|
|
||||||
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
|
|
||||||
ret.push_back(obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,27 +1053,23 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
|||||||
|
|
||||||
// Received
|
// Received
|
||||||
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
|
string account;
|
||||||
|
if (pwalletMain->mapAddressBook.count(r.first))
|
||||||
|
account = pwalletMain->mapAddressBook[r.first];
|
||||||
|
if (fAllAccounts || (account == strAccount))
|
||||||
{
|
{
|
||||||
string account;
|
Object entry;
|
||||||
if (pwalletMain->mapAddressBook.count(r.first))
|
entry.push_back(Pair("account", account));
|
||||||
account = pwalletMain->mapAddressBook[r.first];
|
entry.push_back(Pair("address", r.first.ToString()));
|
||||||
if (fAllAccounts || (account == strAccount))
|
entry.push_back(Pair("category", "receive"));
|
||||||
{
|
entry.push_back(Pair("amount", ValueFromAmount(r.second)));
|
||||||
Object entry;
|
if (fLong)
|
||||||
entry.push_back(Pair("account", account));
|
WalletTxToJSON(wtx, entry);
|
||||||
entry.push_back(Pair("address", r.first.ToString()));
|
ret.push_back(entry);
|
||||||
entry.push_back(Pair("category", "receive"));
|
|
||||||
entry.push_back(Pair("amount", ValueFromAmount(r.second)));
|
|
||||||
if (fLong)
|
|
||||||
WalletTxToJSON(wtx, entry);
|
|
||||||
ret.push_back(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
|
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
|
||||||
@ -1167,41 +1109,38 @@ Value listtransactions(const Array& params, bool fHelp)
|
|||||||
Array ret;
|
Array ret;
|
||||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||||
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
// Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
|
||||||
|
typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
|
||||||
|
typedef multimap<int64, TxPair > TxItems;
|
||||||
|
TxItems txByTime;
|
||||||
|
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
// Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
|
CWalletTx* wtx = &((*it).second);
|
||||||
typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
|
txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
|
||||||
typedef multimap<int64, TxPair > TxItems;
|
|
||||||
TxItems txByTime;
|
|
||||||
|
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
|
||||||
{
|
|
||||||
CWalletTx* wtx = &((*it).second);
|
|
||||||
txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
|
|
||||||
}
|
|
||||||
list<CAccountingEntry> acentries;
|
|
||||||
walletdb.ListAccountCreditDebit(strAccount, acentries);
|
|
||||||
BOOST_FOREACH(CAccountingEntry& entry, acentries)
|
|
||||||
{
|
|
||||||
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now: iterate backwards until we have nCount items to return:
|
|
||||||
TxItems::reverse_iterator it = txByTime.rbegin();
|
|
||||||
if (txByTime.size() > nFrom) std::advance(it, nFrom);
|
|
||||||
for (; it != txByTime.rend(); ++it)
|
|
||||||
{
|
|
||||||
CWalletTx *const pwtx = (*it).second.first;
|
|
||||||
if (pwtx != 0)
|
|
||||||
ListTransactions(*pwtx, strAccount, 0, true, ret);
|
|
||||||
CAccountingEntry *const pacentry = (*it).second.second;
|
|
||||||
if (pacentry != 0)
|
|
||||||
AcentryToJSON(*pacentry, strAccount, ret);
|
|
||||||
|
|
||||||
if (ret.size() >= nCount) break;
|
|
||||||
}
|
|
||||||
// ret is now newest to oldest
|
|
||||||
}
|
}
|
||||||
|
list<CAccountingEntry> acentries;
|
||||||
|
walletdb.ListAccountCreditDebit(strAccount, acentries);
|
||||||
|
BOOST_FOREACH(CAccountingEntry& entry, acentries)
|
||||||
|
{
|
||||||
|
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now: iterate backwards until we have nCount items to return:
|
||||||
|
TxItems::reverse_iterator it = txByTime.rbegin();
|
||||||
|
if (txByTime.size() > nFrom) std::advance(it, nFrom);
|
||||||
|
for (; it != txByTime.rend(); ++it)
|
||||||
|
{
|
||||||
|
CWalletTx *const pwtx = (*it).second.first;
|
||||||
|
if (pwtx != 0)
|
||||||
|
ListTransactions(*pwtx, strAccount, 0, true, ret);
|
||||||
|
CAccountingEntry *const pacentry = (*it).second.second;
|
||||||
|
if (pacentry != 0)
|
||||||
|
AcentryToJSON(*pacentry, strAccount, ret);
|
||||||
|
|
||||||
|
if (ret.size() >= nCount) break;
|
||||||
|
}
|
||||||
|
// ret is now newest to oldest
|
||||||
|
|
||||||
// Make sure we return only last nCount items (sends-to-self might give us an extra):
|
// Make sure we return only last nCount items (sends-to-self might give us an extra):
|
||||||
if (ret.size() > nCount)
|
if (ret.size() > nCount)
|
||||||
@ -1227,34 +1166,30 @@ Value listaccounts(const Array& params, bool fHelp)
|
|||||||
nMinDepth = params[0].get_int();
|
nMinDepth = params[0].get_int();
|
||||||
|
|
||||||
map<string, int64> mapAccountBalances;
|
map<string, int64> mapAccountBalances;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
|
||||||
{
|
mapAccountBalances[entry.second] = 0;
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
|
}
|
||||||
if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
|
|
||||||
mapAccountBalances[entry.second] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
|
{
|
||||||
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
int64 nGeneratedImmature, nGeneratedMature, nFee;
|
||||||
|
string strSentAccount;
|
||||||
|
list<pair<CBitcoinAddress, int64> > listReceived;
|
||||||
|
list<pair<CBitcoinAddress, int64> > listSent;
|
||||||
|
wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
|
||||||
|
mapAccountBalances[strSentAccount] -= nFee;
|
||||||
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
|
||||||
|
mapAccountBalances[strSentAccount] -= s.second;
|
||||||
|
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = (*it).second;
|
mapAccountBalances[""] += nGeneratedMature;
|
||||||
int64 nGeneratedImmature, nGeneratedMature, nFee;
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
|
||||||
string strSentAccount;
|
if (pwalletMain->mapAddressBook.count(r.first))
|
||||||
list<pair<CBitcoinAddress, int64> > listReceived;
|
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
|
||||||
list<pair<CBitcoinAddress, int64> > listSent;
|
else
|
||||||
wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
|
mapAccountBalances[""] += r.second;
|
||||||
mapAccountBalances[strSentAccount] -= nFee;
|
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
|
|
||||||
mapAccountBalances[strSentAccount] -= s.second;
|
|
||||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
|
||||||
{
|
|
||||||
mapAccountBalances[""] += nGeneratedMature;
|
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
|
|
||||||
if (pwalletMain->mapAddressBook.count(r.first))
|
|
||||||
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
|
|
||||||
else
|
|
||||||
mapAccountBalances[""] += r.second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,27 +1216,25 @@ Value gettransaction(const Array& params, bool fHelp)
|
|||||||
hash.SetHex(params[0].get_str());
|
hash.SetHex(params[0].get_str());
|
||||||
|
|
||||||
Object entry;
|
Object entry;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
|
||||||
{
|
|
||||||
if (!pwalletMain->mapWallet.count(hash))
|
|
||||||
throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
|
|
||||||
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
|
|
||||||
|
|
||||||
int64 nCredit = wtx.GetCredit();
|
if (!pwalletMain->mapWallet.count(hash))
|
||||||
int64 nDebit = wtx.GetDebit();
|
throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
|
||||||
int64 nNet = nCredit - nDebit;
|
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
|
||||||
int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
|
|
||||||
|
|
||||||
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
|
int64 nCredit = wtx.GetCredit();
|
||||||
if (wtx.IsFromMe())
|
int64 nDebit = wtx.GetDebit();
|
||||||
entry.push_back(Pair("fee", ValueFromAmount(nFee)));
|
int64 nNet = nCredit - nDebit;
|
||||||
|
int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
|
||||||
|
|
||||||
WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
|
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
|
||||||
|
if (wtx.IsFromMe())
|
||||||
|
entry.push_back(Pair("fee", ValueFromAmount(nFee)));
|
||||||
|
|
||||||
Array details;
|
WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
|
||||||
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
|
|
||||||
entry.push_back(Pair("details", details));
|
Array details;
|
||||||
}
|
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
|
||||||
|
entry.push_back(Pair("details", details));
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@ -1332,13 +1265,10 @@ Value keypoolrefill(const Array& params, bool fHelp)
|
|||||||
"keypoolrefill\n"
|
"keypoolrefill\n"
|
||||||
"Fills the keypool.");
|
"Fills the keypool.");
|
||||||
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
if (pwalletMain->IsLocked())
|
||||||
{
|
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
||||||
if (pwalletMain->IsLocked())
|
|
||||||
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
|
||||||
|
|
||||||
pwalletMain->TopUpKeyPool();
|
pwalletMain->TopUpKeyPool();
|
||||||
}
|
|
||||||
|
|
||||||
if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
|
if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
|
||||||
throw JSONRPCError(-4, "Error refreshing keypool.");
|
throw JSONRPCError(-4, "Error refreshing keypool.");
|
||||||
@ -1407,24 +1337,21 @@ Value walletpassphrase(const Array& params, bool fHelp)
|
|||||||
mlock(&strWalletPass[0], strWalletPass.capacity());
|
mlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
strWalletPass = params[0].get_str();
|
strWalletPass = params[0].get_str();
|
||||||
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
if (strWalletPass.length() > 0)
|
||||||
{
|
{
|
||||||
if (strWalletPass.length() > 0)
|
if (!pwalletMain->Unlock(strWalletPass))
|
||||||
{
|
{
|
||||||
if (!pwalletMain->Unlock(strWalletPass))
|
|
||||||
{
|
|
||||||
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
|
||||||
munlock(&strWalletPass[0], strWalletPass.capacity());
|
|
||||||
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
|
||||||
}
|
|
||||||
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
munlock(&strWalletPass[0], strWalletPass.capacity());
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||||
}
|
}
|
||||||
else
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
throw runtime_error(
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
"walletpassphrase <passphrase> <timeout>\n"
|
|
||||||
"Stores the wallet decryption key in memory for <timeout> seconds.");
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw runtime_error(
|
||||||
|
"walletpassphrase <passphrase> <timeout>\n"
|
||||||
|
"Stores the wallet decryption key in memory for <timeout> seconds.");
|
||||||
|
|
||||||
CreateThread(ThreadTopUpKeyPool, NULL);
|
CreateThread(ThreadTopUpKeyPool, NULL);
|
||||||
int* pnSleepTime = new int(params[1].get_int());
|
int* pnSleepTime = new int(params[1].get_int());
|
||||||
@ -1553,11 +1480,8 @@ Value validateaddress(const Array& params, bool fHelp)
|
|||||||
string currentAddress = address.ToString();
|
string currentAddress = address.ToString();
|
||||||
ret.push_back(Pair("address", currentAddress));
|
ret.push_back(Pair("address", currentAddress));
|
||||||
ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
|
ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
if (pwalletMain->mapAddressBook.count(address))
|
||||||
{
|
ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
|
||||||
if (pwalletMain->mapAddressBook.count(address))
|
|
||||||
ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2233,7 +2157,10 @@ void ThreadRPCServer2(void* parg)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Execute
|
// Execute
|
||||||
Value result = (*(*mi).second)(params, false);
|
Value result;
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
|
result = (*(*mi).second)(params, false);
|
||||||
|
|
||||||
// Send reply
|
// Send reply
|
||||||
string strReply = JSONRPCReply(result, Value::null, id);
|
string strReply = JSONRPCReply(result, Value::null, id);
|
||||||
|
110
src/script.cpp
110
src/script.cpp
@ -1033,48 +1033,45 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Compile solution
|
// Compile solution
|
||||||
CRITICAL_BLOCK(keystore.cs_KeyStore)
|
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
if (item.first == OP_PUBKEY)
|
||||||
{
|
{
|
||||||
if (item.first == OP_PUBKEY)
|
// Sign
|
||||||
{
|
const valtype& vchPubKey = item.second;
|
||||||
// Sign
|
CKey key;
|
||||||
const valtype& vchPubKey = item.second;
|
if (!keystore.GetKey(Hash160(vchPubKey), key))
|
||||||
CKey key;
|
|
||||||
if (!keystore.GetKey(Hash160(vchPubKey), key))
|
|
||||||
return false;
|
|
||||||
if (key.GetPubKey() != vchPubKey)
|
|
||||||
return false;
|
|
||||||
if (hash != 0)
|
|
||||||
{
|
|
||||||
vector<unsigned char> vchSig;
|
|
||||||
if (!key.Sign(hash, vchSig))
|
|
||||||
return false;
|
|
||||||
vchSig.push_back((unsigned char)nHashType);
|
|
||||||
scriptSigRet << vchSig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item.first == OP_PUBKEYHASH)
|
|
||||||
{
|
|
||||||
// Sign and give pubkey
|
|
||||||
CKey key;
|
|
||||||
if (!keystore.GetKey(uint160(item.second), key))
|
|
||||||
return false;
|
|
||||||
if (hash != 0)
|
|
||||||
{
|
|
||||||
vector<unsigned char> vchSig;
|
|
||||||
if (!key.Sign(hash, vchSig))
|
|
||||||
return false;
|
|
||||||
vchSig.push_back((unsigned char)nHashType);
|
|
||||||
scriptSigRet << vchSig << key.GetPubKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
|
if (key.GetPubKey() != vchPubKey)
|
||||||
|
return false;
|
||||||
|
if (hash != 0)
|
||||||
|
{
|
||||||
|
vector<unsigned char> vchSig;
|
||||||
|
if (!key.Sign(hash, vchSig))
|
||||||
|
return false;
|
||||||
|
vchSig.push_back((unsigned char)nHashType);
|
||||||
|
scriptSigRet << vchSig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (item.first == OP_PUBKEYHASH)
|
||||||
|
{
|
||||||
|
// Sign and give pubkey
|
||||||
|
CKey key;
|
||||||
|
if (!keystore.GetKey(uint160(item.second), key))
|
||||||
|
return false;
|
||||||
|
if (hash != 0)
|
||||||
|
{
|
||||||
|
vector<unsigned char> vchSig;
|
||||||
|
if (!key.Sign(hash, vchSig))
|
||||||
|
return false;
|
||||||
|
vchSig.push_back((unsigned char)nHashType);
|
||||||
|
scriptSigRet << vchSig << key.GetPubKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1095,35 +1092,31 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Compile solution
|
// Compile solution
|
||||||
CRITICAL_BLOCK(keystore.cs_KeyStore)
|
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
if (item.first == OP_PUBKEY)
|
||||||
{
|
{
|
||||||
if (item.first == OP_PUBKEY)
|
const valtype& vchPubKey = item.second;
|
||||||
{
|
vector<unsigned char> vchPubKeyFound;
|
||||||
const valtype& vchPubKey = item.second;
|
if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
|
||||||
vector<unsigned char> vchPubKeyFound;
|
|
||||||
if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
|
|
||||||
return false;
|
|
||||||
if (vchPubKeyFound != vchPubKey)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (item.first == OP_PUBKEYHASH)
|
|
||||||
{
|
|
||||||
if (!keystore.HaveKey(uint160(item.second)))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
if (vchPubKeyFound != vchPubKey)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (item.first == OP_PUBKEYHASH)
|
||||||
|
{
|
||||||
|
if (!keystore.HaveKey(uint160(item.second)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires either keystore==0, or a lock on keystore->cs_KeyStore
|
|
||||||
bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
|
bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
|
||||||
{
|
{
|
||||||
vector<pair<opcodetype, valtype> > vSolution;
|
vector<pair<opcodetype, valtype> > vSolution;
|
||||||
@ -1146,8 +1139,7 @@ bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* ke
|
|||||||
bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
|
bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
|
||||||
{
|
{
|
||||||
if (keystore)
|
if (keystore)
|
||||||
CRITICAL_BLOCK(keystore->cs_KeyStore)
|
return ExtractAddressInner(scriptPubKey, keystore, addressRet);
|
||||||
return ExtractAddressInner(scriptPubKey, keystore, addressRet);
|
|
||||||
else
|
else
|
||||||
return ExtractAddressInner(scriptPubKey, NULL, addressRet);
|
return ExtractAddressInner(scriptPubKey, NULL, addressRet);
|
||||||
return false;
|
return false;
|
||||||
|
383
src/ui.cpp
383
src/ui.cpp
@ -708,7 +708,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
|||||||
CBitcoinAddress address;
|
CBitcoinAddress address;
|
||||||
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address))
|
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address))
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
//strDescription += _("Received payment to ");
|
//strDescription += _("Received payment to ");
|
||||||
//strDescription += _("Received with address ");
|
//strDescription += _("Received with address ");
|
||||||
@ -792,7 +792,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
string strDescription = _("To: ");
|
string strDescription = _("To: ");
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
if (pwalletMain->mapAddressBook.count(address) && !pwalletMain->mapAddressBook[address].empty())
|
if (pwalletMain->mapAddressBook.count(address) && !pwalletMain->mapAddressBook[address].empty())
|
||||||
strDescription += pwalletMain->mapAddressBook[address] + " ";
|
strDescription += pwalletMain->mapAddressBook[address] + " ";
|
||||||
strDescription += strAddress;
|
strDescription += strAddress;
|
||||||
@ -862,7 +862,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
|
|||||||
// Collect list of wallet transactions and sort newest first
|
// Collect list of wallet transactions and sort newest first
|
||||||
bool fEntered = false;
|
bool fEntered = false;
|
||||||
vector<pair<unsigned int, uint256> > vSorted;
|
vector<pair<unsigned int, uint256> > vSorted;
|
||||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
printf("RefreshListCtrl starting\n");
|
printf("RefreshListCtrl starting\n");
|
||||||
fEntered = true;
|
fEntered = true;
|
||||||
@ -890,7 +890,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
|
|||||||
if (fShutdown)
|
if (fShutdown)
|
||||||
return;
|
return;
|
||||||
bool fEntered = false;
|
bool fEntered = false;
|
||||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
fEntered = true;
|
fEntered = true;
|
||||||
uint256& hash = vSorted[i++].second;
|
uint256& hash = vSorted[i++].second;
|
||||||
@ -913,7 +913,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
|
|||||||
static int64 nLastTime;
|
static int64 nLastTime;
|
||||||
if (GetTime() > nLastTime + 30)
|
if (GetTime() > nLastTime + 30)
|
||||||
{
|
{
|
||||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
nLastTime = GetTime();
|
nLastTime = GetTime();
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
@ -937,7 +937,7 @@ void CMainFrame::RefreshStatusColumn()
|
|||||||
if (nTop == nLastTop && pindexLastBest == pindexBest)
|
if (nTop == nLastTop && pindexLastBest == pindexBest)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
int nStart = nTop;
|
int nStart = nTop;
|
||||||
int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
|
int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
|
||||||
@ -1032,6 +1032,7 @@ void MainFrameRepaint()
|
|||||||
printf("MainFrameRepaint\n");
|
printf("MainFrameRepaint\n");
|
||||||
wxPaintEvent event;
|
wxPaintEvent event;
|
||||||
pframeMain->fRefresh = true;
|
pframeMain->fRefresh = true;
|
||||||
|
pframeMain->fRefreshListCtrl = true;
|
||||||
pframeMain->GetEventHandler()->AddPendingEvent(event);
|
pframeMain->GetEventHandler()->AddPendingEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1057,7 +1058,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
|
|||||||
// Update listctrl contents
|
// Update listctrl contents
|
||||||
if (!pwalletMain->vWalletUpdated.empty())
|
if (!pwalletMain->vWalletUpdated.empty())
|
||||||
{
|
{
|
||||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
string strTop;
|
string strTop;
|
||||||
if (m_listCtrl->GetItemCount())
|
if (m_listCtrl->GetItemCount())
|
||||||
@ -1075,7 +1076,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Balance total
|
// Balance total
|
||||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
fPaintedBalance = true;
|
fPaintedBalance = true;
|
||||||
m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + " ");
|
m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + " ");
|
||||||
@ -1247,83 +1248,80 @@ void CMainFrame::OnMenuOptionsChangeWalletPassphrase(wxCommandEvent& event)
|
|||||||
strOldWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
|
strOldWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
|
||||||
_("Passphrase")).ToStdString();
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
|
pwalletMain->Lock();
|
||||||
|
|
||||||
|
if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass))
|
||||||
{
|
{
|
||||||
bool fWasLocked = pwalletMain->IsLocked();
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fWasLocked)
|
||||||
pwalletMain->Lock();
|
pwalletMain->Lock();
|
||||||
|
|
||||||
if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass))
|
string strNewWalletPass;
|
||||||
{
|
strNewWalletPass.reserve(100);
|
||||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
|
||||||
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fWasLocked)
|
// obtain new wallet encrypt/decrypt key, from passphrase
|
||||||
pwalletMain->Lock();
|
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||||
|
// be obtained from disk long after bitcoin has run.
|
||||||
|
strNewWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase for the wallet."),
|
||||||
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
string strNewWalletPass;
|
if (!strNewWalletPass.size())
|
||||||
strNewWalletPass.reserve(100);
|
{
|
||||||
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// obtain new wallet encrypt/decrypt key, from passphrase
|
string strNewWalletPassTest;
|
||||||
// Note that the passphrase is not mlock()d during this entry and could potentially
|
strNewWalletPassTest.reserve(100);
|
||||||
// be obtained from disk long after bitcoin has run.
|
mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
strNewWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase for the wallet."),
|
|
||||||
|
// obtain new wallet encrypt/decrypt key, from passphrase
|
||||||
|
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||||
|
// be obtained from disk long after bitcoin has run.
|
||||||
|
strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
|
||||||
_("Passphrase")).ToStdString();
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
if (!strNewWalletPass.size())
|
if (strNewWalletPassTest != strNewWalletPass)
|
||||||
{
|
{
|
||||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
|
||||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
|
||||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
|
||||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
|
||||||
wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string strNewWalletPassTest;
|
|
||||||
strNewWalletPassTest.reserve(100);
|
|
||||||
mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
|
||||||
|
|
||||||
// obtain new wallet encrypt/decrypt key, from passphrase
|
|
||||||
// Note that the passphrase is not mlock()d during this entry and could potentially
|
|
||||||
// be obtained from disk long after bitcoin has run.
|
|
||||||
strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
|
|
||||||
_("Passphrase")).ToStdString();
|
|
||||||
|
|
||||||
if (strNewWalletPassTest != strNewWalletPass)
|
|
||||||
{
|
|
||||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
|
||||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
|
||||||
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
|
||||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
|
||||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
|
||||||
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
|
||||||
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
|
|
||||||
{
|
|
||||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
|
||||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
|
||||||
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
|
||||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
|
||||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
|
||||||
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
|
||||||
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin");
|
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
|
||||||
|
{
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
|
void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
|
||||||
@ -1387,21 +1385,19 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
|
|||||||
string strName = dialog.GetValue();
|
string strName = dialog.GetValue();
|
||||||
|
|
||||||
string strAddress;
|
string strAddress;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
|
||||||
{
|
|
||||||
bool fWasLocked = pwalletMain->IsLocked();
|
|
||||||
if (!GetWalletPassphrase())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Generate new key
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
|
if (!GetWalletPassphrase())
|
||||||
|
return;
|
||||||
|
|
||||||
if (fWasLocked)
|
// Generate new key
|
||||||
pwalletMain->Lock();
|
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
|
||||||
}
|
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
pwalletMain->SetAddressBookName(strAddress, strName);
|
pwalletMain->SetAddressBookName(strAddress, strName);
|
||||||
SetDefaultReceivingAddress(strAddress);
|
SetDefaultReceivingAddress(strAddress);
|
||||||
}
|
}
|
||||||
@ -1420,7 +1416,7 @@ void CMainFrame::OnListItemActivated(wxListEvent& event)
|
|||||||
{
|
{
|
||||||
uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
|
uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
|
||||||
CWalletTx wtx;
|
CWalletTx wtx;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
||||||
if (mi == pwalletMain->mapWallet.end())
|
if (mi == pwalletMain->mapWallet.end())
|
||||||
@ -1451,7 +1447,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
|||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
|
SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
|
||||||
#endif
|
#endif
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
string strHTML;
|
string strHTML;
|
||||||
strHTML.reserve(4000);
|
strHTML.reserve(4000);
|
||||||
@ -1662,7 +1658,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
|||||||
strHTML += HtmlEscape(wtx.ToString(), true);
|
strHTML += HtmlEscape(wtx.ToString(), true);
|
||||||
|
|
||||||
strHTML += "<br><b>Inputs:</b><br>";
|
strHTML += "<br><b>Inputs:</b><br>";
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||||
{
|
{
|
||||||
@ -2160,38 +2156,39 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
|||||||
|
|
||||||
if (fBitcoinAddress)
|
if (fBitcoinAddress)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
if (!GetWalletPassphrase())
|
||||||
{
|
return;
|
||||||
bool fWasLocked = pwalletMain->IsLocked();
|
|
||||||
if (!GetWalletPassphrase())
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
string strError;
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
|
{
|
||||||
// Send to bitcoin address
|
// Send to bitcoin address
|
||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
scriptPubKey.SetBitcoinAddress(address);
|
scriptPubKey.SetBitcoinAddress(address);
|
||||||
|
|
||||||
string strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
|
strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
|
||||||
if (strError == "")
|
}
|
||||||
wxMessageBox(_("Payment sent "), _("Sending..."));
|
if (strError == "")
|
||||||
else if (strError == "ABORTED")
|
wxMessageBox(_("Payment sent "), _("Sending..."));
|
||||||
{
|
else if (strError == "ABORTED")
|
||||||
if (fWasLocked)
|
{
|
||||||
pwalletMain->Lock();
|
|
||||||
return; // leave send dialog open
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wxMessageBox(strError + " ", _("Sending..."));
|
|
||||||
EndModal(false);
|
|
||||||
if (fWasLocked)
|
|
||||||
pwalletMain->Lock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fWasLocked)
|
if (fWasLocked)
|
||||||
pwalletMain->Lock();
|
pwalletMain->Lock();
|
||||||
}
|
return; // leave send dialog open
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(strError + " ", _("Sending..."));
|
||||||
|
EndModal(false);
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2212,7 +2209,7 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
if (!pwalletMain->mapAddressBook.count(address))
|
if (!pwalletMain->mapAddressBook.count(address))
|
||||||
pwalletMain->SetAddressBookName(strAddress, "");
|
pwalletMain->SetAddressBookName(strAddress, "");
|
||||||
|
|
||||||
@ -2464,83 +2461,89 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
// Pay
|
||||||
|
if (!Status(_("Creating transaction...")))
|
||||||
|
return;
|
||||||
|
if (nPrice + nTransactionFee > pwalletMain->GetBalance())
|
||||||
{
|
{
|
||||||
// Pay
|
Error(_("Insufficient funds"));
|
||||||
if (!Status(_("Creating transaction...")))
|
return;
|
||||||
return;
|
}
|
||||||
if (nPrice + nTransactionFee > pwalletMain->GetBalance())
|
|
||||||
{
|
|
||||||
Error(_("Insufficient funds"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CReserveKey reservekey(pwalletMain);
|
CReserveKey reservekey(pwalletMain);
|
||||||
int64 nFeeRequired;
|
int64 nFeeRequired;
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
{
|
if (!GetWalletPassphrase())
|
||||||
bool fWasLocked = pwalletMain->IsLocked();
|
return;
|
||||||
if (!GetWalletPassphrase())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
|
bool fTxCreated = false;
|
||||||
{
|
CRITICAL_BLOCK(cs_main)
|
||||||
if (nPrice + nFeeRequired > pwalletMain->GetBalance())
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
|
{
|
||||||
else
|
fTxCreated = pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired);
|
||||||
Error(_("Transaction creation failed"));
|
}
|
||||||
return;
|
if (!fTxCreated)
|
||||||
}
|
{
|
||||||
|
if (nPrice + nFeeRequired > pwalletMain->GetBalance())
|
||||||
|
Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
|
||||||
|
else
|
||||||
|
Error(_("Transaction creation failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (fWasLocked)
|
if (fWasLocked)
|
||||||
pwalletMain->Lock();
|
pwalletMain->Lock();
|
||||||
}
|
|
||||||
|
|
||||||
// Transaction fee
|
// Transaction fee
|
||||||
if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this))
|
if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this))
|
||||||
{
|
{
|
||||||
Error(_("Transaction aborted"));
|
Error(_("Transaction aborted"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we're still connected
|
// Make sure we're still connected
|
||||||
CNode* pnode = ConnectNode(addr, 2 * 60 * 60);
|
CNode* pnode = ConnectNode(addr, 2 * 60 * 60);
|
||||||
if (!pnode)
|
if (!pnode)
|
||||||
{
|
{
|
||||||
Error(_("Lost connection, transaction cancelled"));
|
Error(_("Lost connection, transaction cancelled"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last chance to cancel
|
// Last chance to cancel
|
||||||
Sleep(50);
|
Sleep(50);
|
||||||
|
if (!Status())
|
||||||
|
return;
|
||||||
|
fCanCancel = false;
|
||||||
|
if (fAbort)
|
||||||
|
{
|
||||||
|
fCanCancel = true;
|
||||||
if (!Status())
|
if (!Status())
|
||||||
return;
|
return;
|
||||||
fCanCancel = false;
|
fCanCancel = false;
|
||||||
if (fAbort)
|
|
||||||
{
|
|
||||||
fCanCancel = true;
|
|
||||||
if (!Status())
|
|
||||||
return;
|
|
||||||
fCanCancel = false;
|
|
||||||
}
|
|
||||||
if (!Status(_("Sending payment...")))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Commit
|
|
||||||
if (!pwalletMain->CommitTransaction(wtx, reservekey))
|
|
||||||
{
|
|
||||||
Error(_("The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send payment tx to seller, with response going to OnReply3 via event handler
|
|
||||||
CWalletTx wtxSend = wtx;
|
|
||||||
wtxSend.fFromMe = false;
|
|
||||||
pnode->PushRequest("submitorder", wtxSend, SendingDialogOnReply3, this);
|
|
||||||
|
|
||||||
Status(_("Waiting for confirmation..."));
|
|
||||||
MainFrameRepaint();
|
|
||||||
}
|
}
|
||||||
|
if (!Status(_("Sending payment...")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Commit
|
||||||
|
bool fTxCommitted = false;
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
|
{
|
||||||
|
fTxCommitted = pwalletMain->CommitTransaction(wtx, reservekey);
|
||||||
|
}
|
||||||
|
if (!fTxCommitted)
|
||||||
|
{
|
||||||
|
Error(_("The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send payment tx to seller, with response going to OnReply3 via event handler
|
||||||
|
CWalletTx wtxSend = wtx;
|
||||||
|
wtxSend.fFromMe = false;
|
||||||
|
pnode->PushRequest("submitorder", wtxSend, SendingDialogOnReply3, this);
|
||||||
|
|
||||||
|
Status(_("Waiting for confirmation..."));
|
||||||
|
MainFrameRepaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendingDialogOnReply3(void* parg, CDataStream& vRecv)
|
void SendingDialogOnReply3(void* parg, CDataStream& vRecv)
|
||||||
@ -2621,8 +2624,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
|
|||||||
m_listCtrlReceiving->SetFocus();
|
m_listCtrlReceiving->SetFocus();
|
||||||
|
|
||||||
// Fill listctrl with address book data
|
// Fill listctrl with address book data
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_KeyStore)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
|
||||||
{
|
{
|
||||||
string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
|
string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
|
||||||
@ -2683,7 +2685,7 @@ void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event)
|
|||||||
if (event.IsEditCancelled())
|
if (event.IsEditCancelled())
|
||||||
return;
|
return;
|
||||||
string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
|
string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
pwalletMain->SetAddressBookName(strAddress, string(event.GetText()));
|
pwalletMain->SetAddressBookName(strAddress, string(event.GetText()));
|
||||||
pframeMain->RefreshListCtrl();
|
pframeMain->RefreshListCtrl();
|
||||||
}
|
}
|
||||||
@ -2719,7 +2721,7 @@ void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event)
|
|||||||
if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
|
if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
|
||||||
{
|
{
|
||||||
string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
|
string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
pwalletMain->DelAddressBookName(strAddress);
|
pwalletMain->DelAddressBookName(strAddress);
|
||||||
m_listCtrl->DeleteItem(nIndex);
|
m_listCtrl->DeleteItem(nIndex);
|
||||||
}
|
}
|
||||||
@ -2779,7 +2781,7 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write back
|
// Write back
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
{
|
{
|
||||||
if (strAddress != strAddressOrg)
|
if (strAddress != strAddressOrg)
|
||||||
pwalletMain->DelAddressBookName(strAddressOrg);
|
pwalletMain->DelAddressBookName(strAddressOrg);
|
||||||
@ -2819,22 +2821,19 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
|
|||||||
return;
|
return;
|
||||||
strName = dialog.GetValue();
|
strName = dialog.GetValue();
|
||||||
|
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
{
|
if (!GetWalletPassphrase())
|
||||||
bool fWasLocked = pwalletMain->IsLocked();
|
return;
|
||||||
if (!GetWalletPassphrase())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Generate new key
|
// Generate new key
|
||||||
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
|
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
|
||||||
|
|
||||||
if (fWasLocked)
|
if (fWasLocked)
|
||||||
pwalletMain->Lock();
|
pwalletMain->Lock();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to list and select it
|
// Add to list and select it
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||||
pwalletMain->SetAddressBookName(strAddress, strName);
|
pwalletMain->SetAddressBookName(strAddress, strName);
|
||||||
int nIndex = InsertLine(m_listCtrl, strName, strAddress);
|
int nIndex = InsertLine(m_listCtrl, strName, strAddress);
|
||||||
SetSelection(m_listCtrl, nIndex);
|
SetSelection(m_listCtrl, nIndex);
|
||||||
|
@ -942,17 +942,21 @@ static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lock
|
|||||||
static boost::thread_specific_ptr<LockStack> lockstack;
|
static boost::thread_specific_ptr<LockStack> lockstack;
|
||||||
|
|
||||||
|
|
||||||
static void potential_deadlock_detected(const LockStack& s1, const LockStack& s2)
|
static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2)
|
||||||
{
|
{
|
||||||
printf("POTENTIAL DEADLOCK DETECTED\n");
|
printf("POTENTIAL DEADLOCK DETECTED\n");
|
||||||
printf("Previous lock order was:\n");
|
printf("Previous lock order was:\n");
|
||||||
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
|
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
|
||||||
{
|
{
|
||||||
|
if (i.first == mismatch.first) printf(" (1)");
|
||||||
|
if (i.first == mismatch.second) printf(" (2)");
|
||||||
printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine);
|
printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine);
|
||||||
}
|
}
|
||||||
printf("Current lock order is:\n");
|
printf("Current lock order is:\n");
|
||||||
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
|
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
|
||||||
{
|
{
|
||||||
|
if (i.first == mismatch.first) printf(" (1)");
|
||||||
|
if (i.first == mismatch.second) printf(" (2)");
|
||||||
printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine);
|
printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -979,7 +983,7 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
|
|||||||
std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
|
std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
|
||||||
if (lockorders.count(p2))
|
if (lockorders.count(p2))
|
||||||
{
|
{
|
||||||
potential_deadlock_detected(lockorders[p2], lockorders[p1]);
|
potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
219
src/wallet.cpp
219
src/wallet.cpp
@ -33,7 +33,7 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
|
|||||||
return false;
|
return false;
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
return true;
|
return true;
|
||||||
CRITICAL_BLOCK(cs_pwalletdbEncryption)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
if (pwalletdbEncryption)
|
if (pwalletdbEncryption)
|
||||||
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
|
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
|
||||||
@ -44,14 +44,13 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
|
|||||||
|
|
||||||
bool CWallet::Unlock(const string& strWalletPassphrase)
|
bool CWallet::Unlock(const string& strWalletPassphrase)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
if (!IsLocked())
|
||||||
{
|
return false;
|
||||||
if (!IsLocked())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CCrypter crypter;
|
CCrypter crypter;
|
||||||
CKeyingMaterial vMasterKey;
|
CKeyingMaterial vMasterKey;
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
||||||
{
|
{
|
||||||
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
@ -61,16 +60,15 @@ bool CWallet::Unlock(const string& strWalletPassphrase)
|
|||||||
if (CCryptoKeyStore::Unlock(vMasterKey))
|
if (CCryptoKeyStore::Unlock(vMasterKey))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const string& strNewWalletPassphrase)
|
bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const string& strNewWalletPassphrase)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
bool fWasLocked = IsLocked();
|
||||||
{
|
|
||||||
bool fWasLocked = IsLocked();
|
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
|
{
|
||||||
Lock();
|
Lock();
|
||||||
|
|
||||||
CCrypter crypter;
|
CCrypter crypter;
|
||||||
@ -79,7 +77,7 @@ bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const
|
|||||||
{
|
{
|
||||||
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
return false;
|
return false;
|
||||||
if(!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
||||||
return false;
|
return false;
|
||||||
if (CCryptoKeyStore::Unlock(vMasterKey))
|
if (CCryptoKeyStore::Unlock(vMasterKey))
|
||||||
{
|
{
|
||||||
@ -107,6 +105,7 @@ bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,44 +124,42 @@ public:
|
|||||||
|
|
||||||
bool CWallet::EncryptWallet(const string& strWalletPassphrase)
|
bool CWallet::EncryptWallet(const string& strWalletPassphrase)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_KeyStore)
|
if (IsCrypted())
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
return false;
|
||||||
CRITICAL_BLOCK(cs_pwalletdbEncryption)
|
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
|
||||||
|
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
|
||||||
|
CMasterKey kMasterKey;
|
||||||
|
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
||||||
|
RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
if (IsCrypted())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CKeyingMaterial vMasterKey;
|
|
||||||
RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
|
||||||
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
|
||||||
|
|
||||||
CMasterKey kMasterKey;
|
|
||||||
|
|
||||||
RandAddSeedPerfmon();
|
|
||||||
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
|
||||||
RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
|
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
|
||||||
if (fFileBacked)
|
if (fFileBacked)
|
||||||
{
|
{
|
||||||
@ -191,6 +188,7 @@ bool CWallet::EncryptWallet(const string& strWalletPassphrase)
|
|||||||
|
|
||||||
Lock();
|
Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +197,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
|
|||||||
// Anytime a signature is successfully verified, it's proof the outpoint is spent.
|
// 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
|
// 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.
|
// restored from backup or the user making copies of wallet.dat.
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||||
{
|
{
|
||||||
@ -222,7 +220,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
|
|||||||
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
|
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
|
||||||
{
|
{
|
||||||
uint256 hash = wtxIn.GetHash();
|
uint256 hash = wtxIn.GetHash();
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
// Inserts only if not already there, returns tx inserted or tx found
|
// 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));
|
pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
|
||||||
@ -290,18 +288,21 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
|
|||||||
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
|
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
|
||||||
{
|
{
|
||||||
uint256 hash = tx.GetHash();
|
uint256 hash = tx.GetHash();
|
||||||
bool fExisted = mapWallet.count(hash);
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
if (fExisted && !fUpdate) return false;
|
|
||||||
if (fExisted || IsMine(tx) || IsFromMe(tx))
|
|
||||||
{
|
{
|
||||||
CWalletTx wtx(this,tx);
|
bool fExisted = mapWallet.count(hash);
|
||||||
// Get merkle branch if transaction was found in a block
|
if (fExisted && !fUpdate) return false;
|
||||||
if (pblock)
|
if (fExisted || IsMine(tx) || IsFromMe(tx))
|
||||||
wtx.SetMerkleBranch(pblock);
|
{
|
||||||
return AddToWallet(wtx);
|
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);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
WalletUpdateSpent(tx);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +310,7 @@ bool CWallet::EraseFromWallet(uint256 hash)
|
|||||||
{
|
{
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
return false;
|
return false;
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
if (mapWallet.erase(hash))
|
if (mapWallet.erase(hash))
|
||||||
CWalletDB(strWalletFile).EraseTx(hash);
|
CWalletDB(strWalletFile).EraseTx(hash);
|
||||||
@ -320,7 +321,7 @@ bool CWallet::EraseFromWallet(uint256 hash)
|
|||||||
|
|
||||||
bool CWallet::IsMine(const CTxIn &txin) const
|
bool CWallet::IsMine(const CTxIn &txin) const
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
||||||
if (mi != mapWallet.end())
|
if (mi != mapWallet.end())
|
||||||
@ -336,7 +337,7 @@ bool CWallet::IsMine(const CTxIn &txin) const
|
|||||||
|
|
||||||
int64 CWallet::GetDebit(const CTxIn &txin) const
|
int64 CWallet::GetDebit(const CTxIn &txin) const
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
||||||
if (mi != mapWallet.end())
|
if (mi != mapWallet.end())
|
||||||
@ -352,19 +353,6 @@ int64 CWallet::GetDebit(const CTxIn &txin) const
|
|||||||
|
|
||||||
int64 CWalletTx::GetTxTime() const
|
int64 CWalletTx::GetTxTime() const
|
||||||
{
|
{
|
||||||
if (!fTimeReceivedIsTxTime && hashBlock != 0)
|
|
||||||
{
|
|
||||||
// If we did not receive the transaction directly, we rely on the block's
|
|
||||||
// time to figure out when it happened. We use the median over a range
|
|
||||||
// of blocks to try to filter out inaccurate block times.
|
|
||||||
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
|
|
||||||
if (mi != mapBlockIndex.end())
|
|
||||||
{
|
|
||||||
CBlockIndex* pindex = (*mi).second;
|
|
||||||
if (pindex)
|
|
||||||
return pindex->GetMedianTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nTimeReceived;
|
return nTimeReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,7 +360,7 @@ int CWalletTx::GetRequestCount() const
|
|||||||
{
|
{
|
||||||
// Returns -1 if it wasn't being tracked
|
// Returns -1 if it wasn't being tracked
|
||||||
int nRequests = -1;
|
int nRequests = -1;
|
||||||
CRITICAL_BLOCK(pwallet->cs_mapRequestCount)
|
CRITICAL_BLOCK(pwallet->cs_wallet)
|
||||||
{
|
{
|
||||||
if (IsCoinBase())
|
if (IsCoinBase())
|
||||||
{
|
{
|
||||||
@ -478,7 +466,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
|
|||||||
nSent += s.second;
|
nSent += s.second;
|
||||||
nFee = allFee;
|
nFee = allFee;
|
||||||
}
|
}
|
||||||
CRITICAL_BLOCK(pwallet->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwallet->cs_wallet)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
|
||||||
{
|
{
|
||||||
@ -508,7 +496,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
|
|||||||
vWorkQueue.push_back(txin.prevout.hash);
|
vWorkQueue.push_back(txin.prevout.hash);
|
||||||
|
|
||||||
// This critsect is OK because txdb is already open
|
// This critsect is OK because txdb is already open
|
||||||
CRITICAL_BLOCK(pwallet->cs_mapWallet)
|
CRITICAL_BLOCK(pwallet->cs_wallet)
|
||||||
{
|
{
|
||||||
map<uint256, const CMerkleTx*> mapWalletPrev;
|
map<uint256, const CMerkleTx*> mapWalletPrev;
|
||||||
set<uint256> setAlreadyDone;
|
set<uint256> setAlreadyDone;
|
||||||
@ -564,7 +552,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
CBlockIndex* pindex = pindexStart;
|
CBlockIndex* pindex = pindexStart;
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
while (pindex)
|
while (pindex)
|
||||||
{
|
{
|
||||||
@ -585,7 +573,7 @@ void CWallet::ReacceptWalletTransactions()
|
|||||||
{
|
{
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
bool fRepeat = true;
|
bool fRepeat = true;
|
||||||
while (fRepeat) CRITICAL_BLOCK(cs_mapWallet)
|
while (fRepeat) CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
fRepeat = false;
|
fRepeat = false;
|
||||||
vector<CDiskTxPos> vMissingTx;
|
vector<CDiskTxPos> vMissingTx;
|
||||||
@ -688,7 +676,7 @@ void CWallet::ResendWalletTransactions()
|
|||||||
// Rebroadcast any of our txes that aren't in a block yet
|
// Rebroadcast any of our txes that aren't in a block yet
|
||||||
printf("ResendWalletTransactions()\n");
|
printf("ResendWalletTransactions()\n");
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
// Sort them in chronological order
|
// Sort them in chronological order
|
||||||
multimap<unsigned int, CWalletTx*> mapSorted;
|
multimap<unsigned int, CWalletTx*> mapSorted;
|
||||||
@ -722,7 +710,7 @@ void CWallet::ResendWalletTransactions()
|
|||||||
int64 CWallet::GetBalance() const
|
int64 CWallet::GetBalance() const
|
||||||
{
|
{
|
||||||
int64 nTotal = 0;
|
int64 nTotal = 0;
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
@ -749,7 +737,7 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe
|
|||||||
vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
|
vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
|
||||||
int64 nTotalLower = 0;
|
int64 nTotalLower = 0;
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
vector<const CWalletTx*> vCoins;
|
vector<const CWalletTx*> vCoins;
|
||||||
vCoins.reserve(mapWallet.size());
|
vCoins.reserve(mapWallet.size());
|
||||||
@ -907,10 +895,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
|
|||||||
wtxNew.pwallet = this;
|
wtxNew.pwallet = this;
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
// txdb must be opened before the mapWallet lock
|
// txdb must be opened before the mapWallet lock
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
|
||||||
{
|
{
|
||||||
nFeeRet = nTransactionFee;
|
nFeeRet = nTransactionFee;
|
||||||
loop
|
loop
|
||||||
@ -1021,9 +1009,9 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w
|
|||||||
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
|
printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
|
||||||
{
|
{
|
||||||
// This is only to keep the database open to defeat the auto-flush for the
|
// This is only to keep the database open to defeat the auto-flush for the
|
||||||
// duration of this scope. This is the only place where this optimization
|
// duration of this scope. This is the only place where this optimization
|
||||||
@ -1053,8 +1041,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Track how many getdata requests our transaction gets
|
// Track how many getdata requests our transaction gets
|
||||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
mapRequestCount[wtxNew.GetHash()] = 0;
|
||||||
mapRequestCount[wtxNew.GetHash()] = 0;
|
|
||||||
|
|
||||||
// Broadcast
|
// Broadcast
|
||||||
if (!wtxNew.AcceptToMemoryPool())
|
if (!wtxNew.AcceptToMemoryPool())
|
||||||
@ -1072,29 +1059,26 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// requires cs_main lock
|
|
||||||
string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||||
{
|
{
|
||||||
CReserveKey reservekey(this);
|
CReserveKey reservekey(this);
|
||||||
int64 nFeeRequired;
|
int64 nFeeRequired;
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
|
||||||
|
if (IsLocked())
|
||||||
{
|
{
|
||||||
if (IsLocked())
|
string strError = _("Error: Wallet locked, unable to create transaction ");
|
||||||
{
|
printf("SendMoney() : %s", strError.c_str());
|
||||||
string strError = _("Error: Wallet locked, unable to create transaction ");
|
return strError;
|
||||||
printf("SendMoney() : %s", strError.c_str());
|
}
|
||||||
return strError;
|
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||||
}
|
{
|
||||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
string strError;
|
||||||
{
|
if (nValue + nFeeRequired > GetBalance())
|
||||||
string strError;
|
strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds "), FormatMoney(nFeeRequired).c_str());
|
||||||
if (nValue + nFeeRequired > GetBalance())
|
else
|
||||||
strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds "), FormatMoney(nFeeRequired).c_str());
|
strError = _("Error: Transaction creation failed ");
|
||||||
else
|
printf("SendMoney() : %s", strError.c_str());
|
||||||
strError = _("Error: Transaction creation failed ");
|
return strError;
|
||||||
printf("SendMoney() : %s", strError.c_str());
|
|
||||||
return strError;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
||||||
@ -1109,7 +1093,6 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// requires cs_main lock
|
|
||||||
string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||||
{
|
{
|
||||||
// Check amount
|
// Check amount
|
||||||
@ -1172,7 +1155,7 @@ bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
|
|||||||
|
|
||||||
void CWallet::PrintWallet(const CBlock& block)
|
void CWallet::PrintWallet(const CBlock& block)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
if (mapWallet.count(block.vtx[0].GetHash()))
|
if (mapWallet.count(block.vtx[0].GetHash()))
|
||||||
{
|
{
|
||||||
@ -1185,7 +1168,7 @@ void CWallet::PrintWallet(const CBlock& block)
|
|||||||
|
|
||||||
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
|
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
|
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
|
||||||
if (mi != mapWallet.end())
|
if (mi != mapWallet.end())
|
||||||
@ -1218,10 +1201,7 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
|
|||||||
|
|
||||||
bool CWallet::TopUpKeyPool()
|
bool CWallet::TopUpKeyPool()
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
|
||||||
CRITICAL_BLOCK(cs_setKeyPool)
|
|
||||||
CRITICAL_BLOCK(cs_vMasterKey)
|
|
||||||
{
|
{
|
||||||
if (IsLocked())
|
if (IsLocked())
|
||||||
return false;
|
return false;
|
||||||
@ -1248,9 +1228,7 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
|||||||
{
|
{
|
||||||
nIndex = -1;
|
nIndex = -1;
|
||||||
keypool.vchPubKey.clear();
|
keypool.vchPubKey.clear();
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
|
||||||
CRITICAL_BLOCK(cs_setKeyPool)
|
|
||||||
{
|
{
|
||||||
if (!IsLocked())
|
if (!IsLocked())
|
||||||
TopUpKeyPool();
|
TopUpKeyPool();
|
||||||
@ -1278,10 +1256,7 @@ void CWallet::KeepKey(int64 nIndex)
|
|||||||
if (fFileBacked)
|
if (fFileBacked)
|
||||||
{
|
{
|
||||||
CWalletDB walletdb(strWalletFile);
|
CWalletDB walletdb(strWalletFile);
|
||||||
CRITICAL_BLOCK(cs_main)
|
walletdb.ErasePool(nIndex);
|
||||||
{
|
|
||||||
walletdb.ErasePool(nIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
printf("keypool keep %"PRI64d"\n", nIndex);
|
printf("keypool keep %"PRI64d"\n", nIndex);
|
||||||
}
|
}
|
||||||
@ -1289,7 +1264,7 @@ void CWallet::KeepKey(int64 nIndex)
|
|||||||
void CWallet::ReturnKey(int64 nIndex)
|
void CWallet::ReturnKey(int64 nIndex)
|
||||||
{
|
{
|
||||||
// Return to key pool
|
// Return to key pool
|
||||||
CRITICAL_BLOCK(cs_setKeyPool)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
setKeyPool.insert(nIndex);
|
setKeyPool.insert(nIndex);
|
||||||
printf("keypool return %"PRI64d"\n", nIndex);
|
printf("keypool return %"PRI64d"\n", nIndex);
|
||||||
}
|
}
|
||||||
|
15
src/wallet.h
15
src/wallet.h
@ -20,14 +20,14 @@ private:
|
|||||||
bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
|
bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
|
||||||
|
|
||||||
CWalletDB *pwalletdbEncryption;
|
CWalletDB *pwalletdbEncryption;
|
||||||
CCriticalSection cs_pwalletdbEncryption;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
mutable CCriticalSection cs_wallet;
|
||||||
|
|
||||||
bool fFileBacked;
|
bool fFileBacked;
|
||||||
std::string strWalletFile;
|
std::string strWalletFile;
|
||||||
|
|
||||||
std::set<int64> setKeyPool;
|
std::set<int64> setKeyPool;
|
||||||
CCriticalSection cs_setKeyPool;
|
|
||||||
|
|
||||||
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
|
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
|
||||||
MasterKeyMap mapMasterKeys;
|
MasterKeyMap mapMasterKeys;
|
||||||
@ -47,15 +47,12 @@ public:
|
|||||||
pwalletdbEncryption = NULL;
|
pwalletdbEncryption = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutable CCriticalSection cs_mapWallet;
|
|
||||||
std::map<uint256, CWalletTx> mapWallet;
|
std::map<uint256, CWalletTx> mapWallet;
|
||||||
std::vector<uint256> vWalletUpdated;
|
std::vector<uint256> vWalletUpdated;
|
||||||
|
|
||||||
std::map<uint256, int> mapRequestCount;
|
std::map<uint256, int> mapRequestCount;
|
||||||
mutable CCriticalSection cs_mapRequestCount;
|
|
||||||
|
|
||||||
std::map<CBitcoinAddress, std::string> mapAddressBook;
|
std::map<CBitcoinAddress, std::string> mapAddressBook;
|
||||||
mutable CCriticalSection cs_mapAddressBook;
|
|
||||||
|
|
||||||
std::vector<unsigned char> vchDefaultKey;
|
std::vector<unsigned char> vchDefaultKey;
|
||||||
|
|
||||||
@ -107,7 +104,7 @@ public:
|
|||||||
{
|
{
|
||||||
CBitcoinAddress address;
|
CBitcoinAddress address;
|
||||||
if (ExtractAddress(txout.scriptPubKey, this, address))
|
if (ExtractAddress(txout.scriptPubKey, this, address))
|
||||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
if (!mapAddressBook.count(address))
|
if (!mapAddressBook.count(address))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
@ -171,15 +168,13 @@ public:
|
|||||||
int LoadWallet(bool& fFirstRunRet);
|
int LoadWallet(bool& fFirstRunRet);
|
||||||
// bool BackupWallet(const std::string& strDest);
|
// bool BackupWallet(const std::string& strDest);
|
||||||
|
|
||||||
// requires cs_mapAddressBook lock
|
|
||||||
bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName);
|
bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName);
|
||||||
|
|
||||||
// requires cs_mapAddressBook lock
|
|
||||||
bool DelAddressBookName(const CBitcoinAddress& address);
|
bool DelAddressBookName(const CBitcoinAddress& address);
|
||||||
|
|
||||||
void UpdatedTransaction(const uint256 &hashTx)
|
void UpdatedTransaction(const uint256 &hashTx)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
vWalletUpdated.push_back(hashTx);
|
vWalletUpdated.push_back(hashTx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +182,7 @@ public:
|
|||||||
|
|
||||||
void Inventory(const uint256 &hash)
|
void Inventory(const uint256 &hash)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
CRITICAL_BLOCK(cs_wallet)
|
||||||
{
|
{
|
||||||
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
|
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
|
||||||
if (mi != mapRequestCount.end())
|
if (mi != mapRequestCount.end())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user