mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
CWallet class
* A new class CKeyStore manages private keys, and script.cpp depends on access to CKeyStore. * A new class CWallet extends CKeyStore, and contains all former wallet-specific globals; CWallet depends on script.cpp, not the other way around. * Wallet-specific functions in CTransaction/CTxIn/CTxOut (GetDebit, GetCredit, GetChange, IsMine, IsFromMe), are moved to CWallet, taking their former 'this' argument as an explicit parameter * CWalletTx objects know which CWallet they belong to, for convenience, so they have their own direct (and caching) GetDebit/... functions. * Some code was moved from CWalletDB to CWallet, such as handling of reserve keys. * Main.cpp keeps a set of all 'registered' wallets, which should be informed about updates to the block chain, and does not have any notion about any 'main' wallet. Function in main.cpp that require a wallet (such as GenerateCoins), take an explicit CWallet* argument. * The actual CWallet instance used by the application is defined in init.cpp as "CWallet* pwalletMain". rpc.cpp and ui.cpp use this variable. * Functions in main.cpp and db.cpp that are not used by other modules are marked static. * The code for handling the 'submitorder' message is removed, as it not really compatible with the idea that a node is independent from the wallet(s) connected to it, and obsolete anyway.
This commit is contained in:
parent
e89b9f6a2a
commit
64c7ee7e6b
65
src/db.cpp
65
src/db.cpp
@ -10,8 +10,6 @@
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
void ThreadFlushWalletDB(void* parg);
|
||||
|
||||
|
||||
unsigned int nWalletDBUpdated;
|
||||
uint64 nAccountingEntryNumber = 0;
|
||||
@ -150,7 +148,7 @@ void CDB::Close()
|
||||
--mapFileUseCount[strFile];
|
||||
}
|
||||
|
||||
void CloseDb(const string& strFile)
|
||||
void static CloseDb(const string& strFile)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
@ -359,7 +357,7 @@ bool CTxDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork)
|
||||
return Write(string("bnBestInvalidWork"), bnBestInvalidWork);
|
||||
}
|
||||
|
||||
CBlockIndex* InsertBlockIndex(uint256 hash)
|
||||
CBlockIndex static * InsertBlockIndex(uint256 hash)
|
||||
{
|
||||
if (hash == 0)
|
||||
return NULL;
|
||||
@ -584,6 +582,20 @@ bool LoadAddresses()
|
||||
// CWalletDB
|
||||
//
|
||||
|
||||
bool CWalletDB::WriteName(const string& strAddress, const string& strName)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(make_pair(string("name"), strAddress), strName);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseName(const string& strAddress)
|
||||
{
|
||||
// This should only be used for sending addresses, never for receiving addresses,
|
||||
// receiving addresses must always have an address book entry if they're not change return.
|
||||
nWalletDBUpdated++;
|
||||
return Erase(make_pair(string("name"), strAddress));
|
||||
}
|
||||
|
||||
bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
|
||||
{
|
||||
account.SetNull();
|
||||
@ -657,9 +669,9 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
|
||||
}
|
||||
|
||||
|
||||
bool CWalletDB::LoadWallet()
|
||||
bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
{
|
||||
vchDefaultKey.clear();
|
||||
pwallet->vchDefaultKey.clear();
|
||||
int nFileVersion = 0;
|
||||
vector<uint256> vWalletUpgrade;
|
||||
|
||||
@ -671,8 +683,8 @@ bool CWalletDB::LoadWallet()
|
||||
#endif
|
||||
|
||||
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(cs_mapKeys)
|
||||
CRITICAL_BLOCK(pwallet->cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwallet->cs_mapKeys)
|
||||
{
|
||||
// Get cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
@ -699,14 +711,15 @@ bool CWalletDB::LoadWallet()
|
||||
{
|
||||
string strAddress;
|
||||
ssKey >> strAddress;
|
||||
ssValue >> mapAddressBook[strAddress];
|
||||
ssValue >> pwallet->mapAddressBook[strAddress];
|
||||
}
|
||||
else if (strType == "tx")
|
||||
{
|
||||
uint256 hash;
|
||||
ssKey >> hash;
|
||||
CWalletTx& wtx = mapWallet[hash];
|
||||
CWalletTx& wtx = pwallet->mapWallet[hash];
|
||||
ssValue >> wtx;
|
||||
wtx.pwallet = pwallet;
|
||||
|
||||
if (wtx.GetHash() != hash)
|
||||
printf("Error in wallet.dat, hash mismatch\n");
|
||||
@ -757,18 +770,18 @@ bool CWalletDB::LoadWallet()
|
||||
else
|
||||
ssValue >> wkey;
|
||||
|
||||
mapKeys[vchPubKey] = wkey.vchPrivKey;
|
||||
pwallet->mapKeys[vchPubKey] = wkey.vchPrivKey;
|
||||
mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
|
||||
}
|
||||
else if (strType == "defaultkey")
|
||||
{
|
||||
ssValue >> vchDefaultKey;
|
||||
ssValue >> pwallet->vchDefaultKey;
|
||||
}
|
||||
else if (strType == "pool")
|
||||
{
|
||||
int64 nIndex;
|
||||
ssKey >> nIndex;
|
||||
setKeyPool.insert(nIndex);
|
||||
pwallet->setKeyPool.insert(nIndex);
|
||||
}
|
||||
else if (strType == "version")
|
||||
{
|
||||
@ -800,7 +813,7 @@ bool CWalletDB::LoadWallet()
|
||||
}
|
||||
|
||||
BOOST_FOREACH(uint256 hash, vWalletUpgrade)
|
||||
WriteTx(hash, mapWallet[hash]);
|
||||
WriteTx(hash, pwallet->mapWallet[hash]);
|
||||
|
||||
printf("nFileVersion = %d\n", nFileVersion);
|
||||
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
|
||||
@ -830,6 +843,7 @@ bool CWalletDB::LoadWallet()
|
||||
|
||||
void ThreadFlushWalletDB(void* parg)
|
||||
{
|
||||
const string& strFile = ((const string*)parg)[0];
|
||||
static bool fOneThread;
|
||||
if (fOneThread)
|
||||
return;
|
||||
@ -865,7 +879,6 @@ void ThreadFlushWalletDB(void* parg)
|
||||
|
||||
if (nRefCount == 0 && !fShutdown)
|
||||
{
|
||||
string strFile = "wallet.dat";
|
||||
map<string, int>::iterator mi = mapFileUseCount.find(strFile);
|
||||
if (mi != mapFileUseCount.end())
|
||||
{
|
||||
@ -888,26 +901,27 @@ void ThreadFlushWalletDB(void* parg)
|
||||
}
|
||||
}
|
||||
|
||||
void BackupWallet(const string& strDest)
|
||||
bool BackupWallet(const CWallet& wallet, const string& strDest)
|
||||
{
|
||||
if (!wallet.fFileBacked)
|
||||
return false;
|
||||
while (!fShutdown)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
const string strFile = "wallet.dat";
|
||||
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
|
||||
if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
|
||||
{
|
||||
// Flush log data to the dat file
|
||||
CloseDb(strFile);
|
||||
CloseDb(wallet.strWalletFile);
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
mapFileUseCount.erase(strFile);
|
||||
dbenv.lsn_reset(wallet.strWalletFile.c_str(), 0);
|
||||
mapFileUseCount.erase(wallet.strWalletFile);
|
||||
|
||||
// Copy wallet.dat
|
||||
filesystem::path pathSrc(GetDataDir() + "/" + strFile);
|
||||
filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
|
||||
filesystem::path pathDest(strDest);
|
||||
if (filesystem::is_directory(pathDest))
|
||||
pathDest = pathDest / strFile;
|
||||
pathDest = pathDest / wallet.strWalletFile;
|
||||
#if BOOST_VERSION >= 104000
|
||||
filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
|
||||
#else
|
||||
@ -915,11 +929,10 @@ void BackupWallet(const string& strDest)
|
||||
#endif
|
||||
printf("copied wallet.dat to %s\n", pathDest.string().c_str());
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
94
src/db.h
94
src/db.h
@ -12,33 +12,25 @@
|
||||
|
||||
#include <db_cxx.h>
|
||||
|
||||
class CTransaction;
|
||||
class CTxIndex;
|
||||
class CDiskBlockIndex;
|
||||
class CDiskTxPos;
|
||||
class COutPoint;
|
||||
class CUser;
|
||||
class CReview;
|
||||
class CAddress;
|
||||
class CWalletTx;
|
||||
class CWallet;
|
||||
class CAccount;
|
||||
class CAccountingEntry;
|
||||
class CBlockLocator;
|
||||
|
||||
extern std::vector<unsigned char> vchDefaultKey;
|
||||
extern bool fClient;
|
||||
extern int nBestHeight;
|
||||
|
||||
|
||||
extern unsigned int nWalletDBUpdated;
|
||||
extern DbEnv dbenv;
|
||||
|
||||
|
||||
extern void DBFlush(bool fShutdown);
|
||||
extern std::vector<unsigned char> GetKeyFromKeyPool();
|
||||
extern int64 GetOldestKeyPoolTime();
|
||||
extern void ThreadFlushWalletDB(void* parg);
|
||||
|
||||
void ThreadFlushWalletDB(void* parg);
|
||||
bool BackupWallet(const CWallet& wallet, const std::string& strDest);
|
||||
|
||||
|
||||
|
||||
@ -321,9 +313,6 @@ bool LoadAddresses();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class CKeyPool
|
||||
{
|
||||
public:
|
||||
@ -356,7 +345,7 @@ public:
|
||||
class CWalletDB : public CDB
|
||||
{
|
||||
public:
|
||||
CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode)
|
||||
CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
|
||||
{
|
||||
}
|
||||
private:
|
||||
@ -369,23 +358,9 @@ public:
|
||||
return Read(std::make_pair(std::string("name"), strAddress), strName);
|
||||
}
|
||||
|
||||
bool WriteName(const std::string& strAddress, const std::string& strName)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
mapAddressBook[strAddress] = strName;
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("name"), strAddress), strName);
|
||||
}
|
||||
bool WriteName(const std::string& strAddress, const std::string& strName);
|
||||
|
||||
bool EraseName(const std::string& strAddress)
|
||||
{
|
||||
// This should only be used for sending addresses, never for receiving addresses,
|
||||
// receiving addresses must always have an address book entry if they're not change return.
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
mapAddressBook.erase(strAddress);
|
||||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("name"), strAddress));
|
||||
}
|
||||
bool EraseName(const std::string& strAddress);
|
||||
|
||||
bool ReadTx(uint256 hash, CWalletTx& wtx)
|
||||
{
|
||||
@ -435,11 +410,27 @@ public:
|
||||
|
||||
bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
vchDefaultKey = vchPubKey;
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::string("defaultkey"), vchPubKey);
|
||||
}
|
||||
|
||||
bool ReadPool(int64 nPool, CKeyPool& keypool)
|
||||
{
|
||||
return Read(std::make_pair(std::string("pool"), nPool), keypool);
|
||||
}
|
||||
|
||||
bool WritePool(int64 nPool, const CKeyPool& keypool)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("pool"), nPool), keypool);
|
||||
}
|
||||
|
||||
bool ErasePool(int64 nPool)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("pool"), nPool));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ReadSetting(const std::string& strKey, T& value)
|
||||
{
|
||||
@ -459,44 +450,7 @@ public:
|
||||
int64 GetAccountCreditDebit(const std::string& strAccount);
|
||||
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
|
||||
|
||||
bool LoadWallet();
|
||||
protected:
|
||||
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
|
||||
void KeepKey(int64 nIndex);
|
||||
static void ReturnKey(int64 nIndex);
|
||||
friend class CReserveKey;
|
||||
friend std::vector<unsigned char> GetKeyFromKeyPool();
|
||||
friend int64 GetOldestKeyPoolTime();
|
||||
};
|
||||
|
||||
bool LoadWallet(bool& fFirstRunRet);
|
||||
void BackupWallet(const std::string& strDest);
|
||||
|
||||
inline bool SetAddressBookName(const std::string& strAddress, const std::string& strName)
|
||||
{
|
||||
return CWalletDB().WriteName(strAddress, strName);
|
||||
}
|
||||
|
||||
class CReserveKey
|
||||
{
|
||||
protected:
|
||||
int64 nIndex;
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
public:
|
||||
CReserveKey()
|
||||
{
|
||||
nIndex = -1;
|
||||
}
|
||||
|
||||
~CReserveKey()
|
||||
{
|
||||
if (!fShutdown)
|
||||
ReturnKey();
|
||||
}
|
||||
|
||||
std::vector<unsigned char> GetReservedKey();
|
||||
void KeepKey();
|
||||
void ReturnKey();
|
||||
bool LoadWallet(CWallet* pwallet);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
22
src/init.cpp
22
src/init.cpp
@ -13,6 +13,8 @@
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
CWallet* pwalletMain;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Shutdown
|
||||
@ -45,6 +47,8 @@ void Shutdown(void* parg)
|
||||
StopNode();
|
||||
DBFlush(true);
|
||||
boost::filesystem::remove(GetPidFile());
|
||||
UnregisterWallet(pwalletMain);
|
||||
delete pwalletMain;
|
||||
CreateThread(ExitTimeout, NULL);
|
||||
Sleep(50);
|
||||
printf("Bitcoin exiting\n\n");
|
||||
@ -372,16 +376,19 @@ bool AppInit2(int argc, char* argv[])
|
||||
printf("Loading wallet...\n");
|
||||
nStart = GetTimeMillis();
|
||||
bool fFirstRun;
|
||||
if (!LoadWallet(fFirstRun))
|
||||
pwalletMain = new CWallet("wallet.dat");
|
||||
if (!pwalletMain->LoadWallet(fFirstRun))
|
||||
strErrors += _("Error loading wallet.dat \n");
|
||||
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||
|
||||
RegisterWallet(pwalletMain);
|
||||
|
||||
CBlockIndex *pindexRescan = pindexBest;
|
||||
if (GetBoolArg("-rescan"))
|
||||
pindexRescan = pindexGenesisBlock;
|
||||
else
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
CWalletDB walletdb("wallet.dat");
|
||||
CBlockLocator locator;
|
||||
if (walletdb.ReadBestBlock(locator))
|
||||
pindexRescan = locator.GetBlockIndex();
|
||||
@ -390,7 +397,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
{
|
||||
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
|
||||
nStart = GetTimeMillis();
|
||||
ScanForWalletTransactions(pindexRescan, true);
|
||||
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
|
||||
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||
}
|
||||
|
||||
@ -399,10 +406,11 @@ bool AppInit2(int argc, char* argv[])
|
||||
//// debug print
|
||||
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
|
||||
printf("nBestHeight = %d\n", nBestHeight);
|
||||
printf("mapKeys.size() = %d\n", mapKeys.size());
|
||||
printf("mapKeys.size() = %d\n", pwalletMain->mapKeys.size());
|
||||
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
|
||||
printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
|
||||
printf("mapWallet.size() = %d\n", mapWallet.size());
|
||||
printf("mapAddressBook.size() = %d\n", mapAddressBook.size());
|
||||
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
|
||||
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
|
||||
|
||||
if (!strErrors.empty())
|
||||
{
|
||||
@ -411,7 +419,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// Add wallet transactions that aren't already in a block to mapTransactions
|
||||
ReacceptWalletTransactions();
|
||||
pwalletMain->ReacceptWalletTransactions();
|
||||
|
||||
//
|
||||
// Parameters
|
||||
|
@ -4,6 +4,8 @@
|
||||
#ifndef BITCOIN_INIT_H
|
||||
#define BITCOIN_INIT_H
|
||||
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
void Shutdown(void* parg);
|
||||
bool AppInit(int argc, char* argv[]);
|
||||
bool AppInit2(int argc, char* argv[]);
|
||||
|
@ -12,7 +12,7 @@
|
||||
// mapKeys
|
||||
//
|
||||
|
||||
std::vector<unsigned char> GenerateNewKey()
|
||||
std::vector<unsigned char> CKeyStore::GenerateNewKey()
|
||||
{
|
||||
RandAddSeedPerfmon();
|
||||
CKey key;
|
||||
@ -22,12 +22,12 @@ std::vector<unsigned char> GenerateNewKey()
|
||||
return key.GetPubKey();
|
||||
}
|
||||
|
||||
bool AddKey(const CKey& key)
|
||||
bool CKeyStore::AddKey(const CKey& key)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapKeys)
|
||||
{
|
||||
mapKeys[key.GetPubKey()] = key.GetPrivKey();
|
||||
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
|
||||
}
|
||||
return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,23 @@
|
||||
#ifndef BITCOIN_KEYSTORE_H
|
||||
#define BITCOIN_KEYSTORE_H
|
||||
|
||||
bool AddKey(const CKey& key);
|
||||
std::vector<unsigned char> GenerateNewKey();
|
||||
class CKeyStore
|
||||
{
|
||||
public:
|
||||
std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
|
||||
mutable CCriticalSection cs_mapKeys;
|
||||
virtual bool AddKey(const CKey& key);
|
||||
bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
|
||||
{
|
||||
return (mapKeys.count(vchPubKey) > 0);
|
||||
}
|
||||
CPrivKey GetPrivKey(const std::vector<unsigned char> &vchPubKey) const
|
||||
{
|
||||
std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey);
|
||||
if (mi != mapKeys.end())
|
||||
return (*mi).second;
|
||||
}
|
||||
std::vector<unsigned char> GenerateNewKey();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
256
src/main.cpp
256
src/main.cpp
@ -15,8 +15,14 @@ using namespace boost;
|
||||
// Global state
|
||||
//
|
||||
|
||||
CCriticalSection cs_setpwalletRegistered;
|
||||
set<CWallet*> setpwalletRegistered;
|
||||
|
||||
CCriticalSection cs_main;
|
||||
|
||||
CCriticalSection cs_mapPubKeys;
|
||||
map<uint160, vector<unsigned char> > mapPubKeys;
|
||||
|
||||
map<uint256, CTransaction> mapTransactions;
|
||||
CCriticalSection cs_mapTransactions;
|
||||
unsigned int nTransactionsUpdated = 0;
|
||||
@ -39,25 +45,6 @@ multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
|
||||
map<uint256, CDataStream*> mapOrphanTransactions;
|
||||
multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
|
||||
|
||||
map<uint256, CWalletTx> mapWallet;
|
||||
vector<uint256> vWalletUpdated;
|
||||
CCriticalSection cs_mapWallet;
|
||||
|
||||
map<vector<unsigned char>, CPrivKey> mapKeys;
|
||||
map<uint160, vector<unsigned char> > mapPubKeys;
|
||||
CCriticalSection cs_mapKeys;
|
||||
CKey keyUser;
|
||||
|
||||
map<uint256, int> mapRequestCount;
|
||||
CCriticalSection cs_mapRequestCount;
|
||||
|
||||
map<string, string> mapAddressBook;
|
||||
CCriticalSection cs_mapAddressBook;
|
||||
|
||||
set<int64> setKeyPool;
|
||||
CCriticalSection cs_setKeyPool;
|
||||
|
||||
vector<unsigned char> vchDefaultKey;
|
||||
|
||||
double dHashesPerSec;
|
||||
int64 nHPSTimerStart;
|
||||
@ -82,12 +69,97 @@ int fUseUPnP = false;
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// dispatching functions
|
||||
//
|
||||
|
||||
void RegisterWallet(CWallet* pwalletIn)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_setpwalletRegistered)
|
||||
{
|
||||
setpwalletRegistered.insert(pwalletIn);
|
||||
}
|
||||
}
|
||||
|
||||
void UnregisterWallet(CWallet* pwalletIn)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_setpwalletRegistered)
|
||||
{
|
||||
setpwalletRegistered.erase(pwalletIn);
|
||||
}
|
||||
}
|
||||
|
||||
bool static IsFromMe(CTransaction& tx)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
if (pwallet->IsFromMe(tx))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
if (pwallet->GetTransaction(hashTx,wtx))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void static EraseFromWallets(uint256 hash)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
pwallet->EraseFromWallet(hash);
|
||||
}
|
||||
|
||||
void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
|
||||
}
|
||||
|
||||
void static SetBestChain(const CBlockLocator& loc)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
pwallet->SetBestChain(loc);
|
||||
}
|
||||
|
||||
void static UpdatedTransaction(const uint256& hashTx)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
pwallet->UpdatedTransaction(hashTx);
|
||||
}
|
||||
|
||||
void static PrintWallets(const CBlock& block)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
pwallet->PrintWallet(block);
|
||||
}
|
||||
|
||||
void static Inventory(const uint256& hash)
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
pwallet->Inventory(hash);
|
||||
}
|
||||
|
||||
void static ResendWalletTransactions()
|
||||
{
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
pwallet->ResendWalletTransactions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// mapOrphanTransactions
|
||||
//
|
||||
|
||||
void AddOrphanTx(const CDataStream& vMsg)
|
||||
void static AddOrphanTx(const CDataStream& vMsg)
|
||||
{
|
||||
CTransaction tx;
|
||||
CDataStream(vMsg) >> tx;
|
||||
@ -99,7 +171,7 @@ void AddOrphanTx(const CDataStream& vMsg)
|
||||
mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
|
||||
}
|
||||
|
||||
void EraseOrphanTx(uint256 hash)
|
||||
void static EraseOrphanTx(uint256 hash)
|
||||
{
|
||||
if (!mapOrphanTransactions.count(hash))
|
||||
return;
|
||||
@ -357,7 +429,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||
nLastTime = nNow;
|
||||
// -limitfreerelay unit is thousand-bytes-per-minute
|
||||
// At default rate it would take over a month to fill 1GB
|
||||
if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe())
|
||||
if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this))
|
||||
return error("AcceptToMemoryPool() : free transaction rejected by rate limiter");
|
||||
if (fDebug)
|
||||
printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
||||
@ -380,7 +452,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||
///// are we sure this is ok when loading transactions or restoring block txes
|
||||
// If updated, erase old tx from wallet
|
||||
if (ptxOld)
|
||||
EraseFromWallet(ptxOld->GetHash());
|
||||
EraseFromWallets(ptxOld->GetHash());
|
||||
|
||||
printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str());
|
||||
return true;
|
||||
@ -551,8 +623,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint256 GetOrphanRoot(const CBlock* pblock)
|
||||
uint256 static GetOrphanRoot(const CBlock* pblock)
|
||||
{
|
||||
// Work back to the first block in the orphan chain
|
||||
while (mapOrphanBlocks.count(pblock->hashPrevBlock))
|
||||
@ -560,7 +631,7 @@ uint256 GetOrphanRoot(const CBlock* pblock)
|
||||
return pblock->GetHash();
|
||||
}
|
||||
|
||||
int64 GetBlockValue(int nHeight, int64 nFees)
|
||||
int64 static GetBlockValue(int nHeight, int64 nFees)
|
||||
{
|
||||
int64 nSubsidy = 50 * COIN;
|
||||
|
||||
@ -570,7 +641,7 @@ int64 GetBlockValue(int nHeight, int64 nFees)
|
||||
return nSubsidy + nFees;
|
||||
}
|
||||
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
|
||||
unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast)
|
||||
{
|
||||
const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
|
||||
const int64 nTargetSpacing = 10 * 60;
|
||||
@ -647,7 +718,7 @@ bool IsInitialBlockDownload()
|
||||
pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
|
||||
}
|
||||
|
||||
void InvalidChainFound(CBlockIndex* pindexNew)
|
||||
void static InvalidChainFound(CBlockIndex* pindexNew)
|
||||
{
|
||||
if (pindexNew->bnChainWork > bnBestInvalidWork)
|
||||
{
|
||||
@ -923,12 +994,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
|
||||
|
||||
// Watch for transactions paying to me
|
||||
BOOST_FOREACH(CTransaction& tx, vtx)
|
||||
AddToWalletIfInvolvingMe(tx, this, true);
|
||||
SyncWithWallets(tx, this, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
{
|
||||
printf("REORGANIZE\n");
|
||||
|
||||
@ -1066,10 +1137,8 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
// Update best block in wallet (so we can detect restored wallets)
|
||||
if (!IsInitialBlockDownload())
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
const CBlockLocator locator(pindexNew);
|
||||
if (!walletdb.WriteBestBlock(locator))
|
||||
return error("SetBestChain() : WriteWalletBest failed");
|
||||
::SetBestChain(locator);
|
||||
}
|
||||
|
||||
// New best block
|
||||
@ -1123,8 +1192,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
|
||||
{
|
||||
// Notify UI to display prev block's coinbase if it was ours
|
||||
static uint256 hashPrevBestCoinBase;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
vWalletUpdated.push_back(hashPrevBestCoinBase);
|
||||
UpdatedTransaction(hashPrevBestCoinBase);
|
||||
hashPrevBestCoinBase = vtx[0].GetHash();
|
||||
}
|
||||
|
||||
@ -1233,7 +1301,7 @@ bool CBlock::AcceptBlock()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessBlock(CNode* pfrom, CBlock* pblock)
|
||||
bool static ProcessBlock(CNode* pfrom, CBlock* pblock)
|
||||
{
|
||||
// Check for duplicate
|
||||
uint256 hash = pblock->GetHash();
|
||||
@ -1295,7 +1363,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
|
||||
|
||||
|
||||
template<typename Stream>
|
||||
bool ScanMessageStart(Stream& s)
|
||||
bool static ScanMessageStart(Stream& s)
|
||||
{
|
||||
// Scan ahead to the next pchMessageStart, which should normally be immediately
|
||||
// at the file pointer. Leaves file pointer at end of pchMessageStart.
|
||||
@ -1510,7 +1578,7 @@ void PrintBlockTree()
|
||||
for (int i = 0; i < nCol; i++)
|
||||
printf("| ");
|
||||
printf("|\n");
|
||||
}
|
||||
}
|
||||
nPrevCol = nCol;
|
||||
|
||||
// print columns
|
||||
@ -1528,16 +1596,7 @@ void PrintBlockTree()
|
||||
DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),
|
||||
block.vtx.size());
|
||||
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
if (mapWallet.count(block.vtx[0].GetHash()))
|
||||
{
|
||||
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
|
||||
printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
PrintWallets(block);
|
||||
|
||||
// put the main timechain first
|
||||
vector<CBlockIndex*>& vNext = mapNext[pindex];
|
||||
@ -1677,7 +1736,7 @@ bool CAlert::ProcessAlert()
|
||||
//
|
||||
|
||||
|
||||
bool AlreadyHave(CTxDB& txdb, const CInv& inv)
|
||||
bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
|
||||
{
|
||||
switch (inv.type)
|
||||
{
|
||||
@ -1697,7 +1756,7 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
|
||||
char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
|
||||
|
||||
|
||||
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
{
|
||||
static map<unsigned int, vector<unsigned char> > mapReuseKey;
|
||||
RandAddSeedPerfmon();
|
||||
@ -1894,12 +1953,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
|
||||
|
||||
// Track requests for our stuff
|
||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||
{
|
||||
map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
|
||||
if (mi != mapRequestCount.end())
|
||||
(*mi).second++;
|
||||
}
|
||||
Inventory(inv.hash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1952,12 +2006,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
}
|
||||
|
||||
// Track requests for our stuff
|
||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||
{
|
||||
map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
|
||||
if (mi != mapRequestCount.end())
|
||||
(*mi).second++;
|
||||
}
|
||||
Inventory(inv.hash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2045,7 +2094,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
bool fMissingInputs = false;
|
||||
if (tx.AcceptToMemoryPool(true, &fMissingInputs))
|
||||
{
|
||||
AddToWalletIfInvolvingMe(tx, NULL, true);
|
||||
SyncWithWallets(tx, NULL, true);
|
||||
RelayMessage(inv, vMsg);
|
||||
mapAlreadyAskedFor.erase(inv);
|
||||
vWorkQueue.push_back(inv.hash);
|
||||
@ -2066,7 +2115,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
if (tx.AcceptToMemoryPool(true))
|
||||
{
|
||||
printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
|
||||
AddToWalletIfInvolvingMe(tx, NULL, true);
|
||||
SyncWithWallets(tx, NULL, true);
|
||||
RelayMessage(inv, vMsg);
|
||||
mapAlreadyAskedFor.erase(inv);
|
||||
vWorkQueue.push_back(inv.hash);
|
||||
@ -2143,7 +2192,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
|
||||
// Keep giving the same key to the same ip until they use it
|
||||
if (!mapReuseKey.count(pfrom->addr.ip))
|
||||
mapReuseKey[pfrom->addr.ip] = GetKeyFromKeyPool();
|
||||
mapReuseKey[pfrom->addr.ip] = pwalletMain->GetKeyFromKeyPool();
|
||||
|
||||
// Send back approval of order and pubkey to use
|
||||
CScript scriptPubKey;
|
||||
@ -2152,37 +2201,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == "submitorder")
|
||||
{
|
||||
uint256 hashReply;
|
||||
vRecv >> hashReply;
|
||||
|
||||
if (!GetBoolArg("-allowreceivebyip"))
|
||||
{
|
||||
pfrom->PushMessage("reply", hashReply, (int)2);
|
||||
return true;
|
||||
}
|
||||
|
||||
CWalletTx wtxNew;
|
||||
vRecv >> wtxNew;
|
||||
wtxNew.fFromMe = false;
|
||||
|
||||
// Broadcast
|
||||
if (!wtxNew.AcceptWalletTransaction())
|
||||
{
|
||||
pfrom->PushMessage("reply", hashReply, (int)1);
|
||||
return error("submitorder AcceptWalletTransaction() failed, returning error 1");
|
||||
}
|
||||
wtxNew.fTimeReceivedIsTxTime = true;
|
||||
AddToWallet(wtxNew);
|
||||
wtxNew.RelayWalletTransaction();
|
||||
mapReuseKey.erase(pfrom->addr.ip);
|
||||
|
||||
// Send back confirmation
|
||||
pfrom->PushMessage("reply", hashReply, (int)0);
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == "reply")
|
||||
{
|
||||
uint256 hashReply;
|
||||
@ -2239,7 +2257,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ProcessMessages(CNode* pfrom)
|
||||
{
|
||||
CDataStream& vRecv = pfrom->vRecv;
|
||||
@ -2359,8 +2376,6 @@ bool ProcessMessages(CNode* pfrom)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
@ -2483,16 +2498,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
// always trickle our own transactions
|
||||
if (!fTrickleWait)
|
||||
{
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(inv.hash);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
CWalletTx& wtx = (*mi).second;
|
||||
if (wtx.fFromMe)
|
||||
fTrickleWait = true;
|
||||
}
|
||||
}
|
||||
CWalletTx wtx;
|
||||
if (GetTransaction(inv.hash, wtx))
|
||||
if (wtx.fFromMe)
|
||||
fTrickleWait = true;
|
||||
}
|
||||
|
||||
if (fTrickleWait)
|
||||
@ -2565,7 +2574,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
// BitcoinMiner
|
||||
//
|
||||
|
||||
int FormatHashBlocks(void* pbuffer, unsigned int len)
|
||||
int static FormatHashBlocks(void* pbuffer, unsigned int len)
|
||||
{
|
||||
unsigned char* pdata = (unsigned char*)pbuffer;
|
||||
unsigned int blocks = 1 + ((len + 8) / 64);
|
||||
@ -2598,7 +2607,7 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit)
|
||||
// between calls, but periodically or if nNonce is 0xffff0000 or above,
|
||||
// the block is rebuilt and nNonce starts over at zero.
|
||||
//
|
||||
unsigned int ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
|
||||
unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
|
||||
{
|
||||
unsigned int& nNonce = *(unsigned int*)(pdata + 12);
|
||||
for (;;)
|
||||
@ -2855,7 +2864,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash
|
||||
}
|
||||
|
||||
|
||||
bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
|
||||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
|
||||
{
|
||||
uint256 hash = pblock->GetHash();
|
||||
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||
@ -2880,8 +2889,8 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
|
||||
reservekey.KeepKey();
|
||||
|
||||
// Track how many getdata requests this block gets
|
||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||
mapRequestCount[pblock->GetHash()] = 0;
|
||||
CRITICAL_BLOCK(wallet.cs_mapRequestCount)
|
||||
wallet.mapRequestCount[pblock->GetHash()] = 0;
|
||||
|
||||
// Process this block the same as if we had received it from another node
|
||||
if (!ProcessBlock(NULL, pblock))
|
||||
@ -2892,13 +2901,15 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitcoinMiner()
|
||||
void static ThreadBitcoinMiner(void* parg);
|
||||
|
||||
void static BitcoinMiner(CWallet *pwallet)
|
||||
{
|
||||
printf("BitcoinMiner started\n");
|
||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||
|
||||
// Each thread has its own key and counter
|
||||
CReserveKey reservekey;
|
||||
CReserveKey reservekey(pwallet);
|
||||
unsigned int nExtraNonce = 0;
|
||||
int64 nPrevTime = 0;
|
||||
|
||||
@ -2974,7 +2985,7 @@ void BitcoinMiner()
|
||||
assert(hash == pblock->GetHash());
|
||||
|
||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||
CheckWork(pblock.get(), reservekey);
|
||||
CheckWork(pblock.get(), *pwalletMain, reservekey);
|
||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||
break;
|
||||
}
|
||||
@ -3035,12 +3046,13 @@ void BitcoinMiner()
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadBitcoinMiner(void* parg)
|
||||
void static ThreadBitcoinMiner(void* parg)
|
||||
{
|
||||
CWallet* pwallet = (CWallet*)parg;
|
||||
try
|
||||
{
|
||||
vnThreadsRunning[3]++;
|
||||
BitcoinMiner();
|
||||
BitcoinMiner(pwallet);
|
||||
vnThreadsRunning[3]--;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
@ -3058,12 +3070,12 @@ void ThreadBitcoinMiner(void* parg)
|
||||
}
|
||||
|
||||
|
||||
void GenerateBitcoins(bool fGenerate)
|
||||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
|
||||
{
|
||||
if (fGenerateBitcoins != fGenerate)
|
||||
{
|
||||
fGenerateBitcoins = fGenerate;
|
||||
CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
|
||||
WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
|
||||
MainFrameRepaint();
|
||||
}
|
||||
if (fGenerateBitcoins)
|
||||
@ -3078,7 +3090,7 @@ void GenerateBitcoins(bool fGenerate)
|
||||
printf("Starting %d BitcoinMiner threads\n", nAddThreads);
|
||||
for (int i = 0; i < nAddThreads; i++)
|
||||
{
|
||||
if (!CreateThread(ThreadBitcoinMiner, NULL))
|
||||
if (!CreateThread(ThreadBitcoinMiner, pwallet))
|
||||
printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");
|
||||
Sleep(10);
|
||||
}
|
||||
|
131
src/main.h
131
src/main.h
@ -8,21 +8,17 @@
|
||||
#include "net.h"
|
||||
#include "key.h"
|
||||
#include "script.h"
|
||||
#include "db.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
class COutPoint;
|
||||
class CInPoint;
|
||||
class CDiskTxPos;
|
||||
class CCoinBase;
|
||||
class CTxIn;
|
||||
class CTxOut;
|
||||
class CTransaction;
|
||||
class CBlock;
|
||||
class CBlockIndex;
|
||||
class CWalletTx;
|
||||
class CWallet;
|
||||
class CKeyItem;
|
||||
class CReserveKey;
|
||||
class CWalletDB;
|
||||
|
||||
class CMessageHeader;
|
||||
class CAddress;
|
||||
@ -62,15 +58,12 @@ extern CBigNum bnBestChainWork;
|
||||
extern CBigNum bnBestInvalidWork;
|
||||
extern uint256 hashBestChain;
|
||||
extern CBlockIndex* pindexBest;
|
||||
extern std::set<int64> setKeyPool;
|
||||
extern CCriticalSection cs_setKeyPool;
|
||||
extern unsigned int nTransactionsUpdated;
|
||||
extern double dHashesPerSec;
|
||||
extern int64 nHPSTimerStart;
|
||||
extern int64 nTimeBestReceived;
|
||||
extern std::map<std::string, std::string> mapAddressBook;
|
||||
extern CCriticalSection cs_mapAddressBook;
|
||||
|
||||
extern CCriticalSection cs_setpwalletRegistered;
|
||||
extern std::set<CWallet*> setpwalletRegistered;
|
||||
|
||||
// Settings
|
||||
extern int fGenerateBitcoins;
|
||||
@ -90,21 +83,20 @@ class CReserveKey;
|
||||
class CTxDB;
|
||||
class CTxIndex;
|
||||
|
||||
void RegisterWallet(CWallet* pwalletIn);
|
||||
void UnregisterWallet(CWallet* pwalletIn);
|
||||
bool CheckDiskSpace(uint64 nAdditionalBytes=0);
|
||||
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
|
||||
FILE* AppendBlockFile(unsigned int& nFileRet);
|
||||
bool LoadBlockIndex(bool fAllowNew=true);
|
||||
void PrintBlockTree();
|
||||
bool ProcessMessages(CNode* pfrom);
|
||||
bool ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv);
|
||||
bool SendMessages(CNode* pto, bool fSendTrickle);
|
||||
void GenerateBitcoins(bool fGenerate);
|
||||
void ThreadBitcoinMiner(void* parg);
|
||||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
|
||||
CBlock* CreateNewBlock(CReserveKey& reservekey);
|
||||
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime);
|
||||
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
|
||||
bool CheckWork(CBlock* pblock, CReserveKey& reservekey);
|
||||
void BitcoinMiner();
|
||||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||
bool IsInitialBlockDownload();
|
||||
std::string GetWarnings(std::string strFor);
|
||||
@ -120,6 +112,23 @@ std::string GetWarnings(std::string strFor);
|
||||
|
||||
|
||||
|
||||
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
|
||||
|
||||
template<typename T>
|
||||
bool WriteSetting(const std::string& strKey, const T& value)
|
||||
{
|
||||
bool fOk = false;
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
{
|
||||
std::string strWalletFile;
|
||||
if (!GetWalletFile(pwallet, strWalletFile))
|
||||
continue;
|
||||
fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
|
||||
}
|
||||
return fOk;
|
||||
}
|
||||
|
||||
|
||||
class CDiskTxPos
|
||||
{
|
||||
public:
|
||||
@ -302,9 +311,6 @@ public:
|
||||
{
|
||||
printf("%s\n", ToString().c_str());
|
||||
}
|
||||
|
||||
bool IsMine() const;
|
||||
int64 GetDebit() const;
|
||||
};
|
||||
|
||||
|
||||
@ -353,36 +359,6 @@ public:
|
||||
return SerializeHash(*this);
|
||||
}
|
||||
|
||||
bool IsMine() const
|
||||
{
|
||||
return ::IsMine(scriptPubKey);
|
||||
}
|
||||
|
||||
int64 GetCredit() const
|
||||
{
|
||||
if (!MoneyRange(nValue))
|
||||
throw std::runtime_error("CTxOut::GetCredit() : value out of range");
|
||||
return (IsMine() ? nValue : 0);
|
||||
}
|
||||
|
||||
bool IsChange() const
|
||||
{
|
||||
// On a debit transaction, a txout that's mine but isn't in the address book is change
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
if (ExtractPubKey(scriptPubKey, true, vchPubKey))
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int64 GetChange() const
|
||||
{
|
||||
if (!MoneyRange(nValue))
|
||||
throw std::runtime_error("CTxOut::GetChange() : value out of range");
|
||||
return (IsChange() ? nValue : 0);
|
||||
}
|
||||
|
||||
friend bool operator==(const CTxOut& a, const CTxOut& b)
|
||||
{
|
||||
return (a.nValue == b.nValue &&
|
||||
@ -527,57 +503,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsMine() const
|
||||
{
|
||||
BOOST_FOREACH(const CTxOut& txout, vout)
|
||||
if (txout.IsMine())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsFromMe() const
|
||||
{
|
||||
return (GetDebit() > 0);
|
||||
}
|
||||
|
||||
int64 GetDebit() const
|
||||
{
|
||||
int64 nDebit = 0;
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
{
|
||||
nDebit += txin.GetDebit();
|
||||
if (!MoneyRange(nDebit))
|
||||
throw std::runtime_error("CTransaction::GetDebit() : value out of range");
|
||||
}
|
||||
return nDebit;
|
||||
}
|
||||
|
||||
int64 GetCredit() const
|
||||
{
|
||||
int64 nCredit = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, vout)
|
||||
{
|
||||
nCredit += txout.GetCredit();
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error("CTransaction::GetCredit() : value out of range");
|
||||
}
|
||||
return nCredit;
|
||||
}
|
||||
|
||||
int64 GetChange() const
|
||||
{
|
||||
if (IsCoinBase())
|
||||
return 0;
|
||||
int64 nChange = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, vout)
|
||||
{
|
||||
nChange += txout.GetChange();
|
||||
if (!MoneyRange(nChange))
|
||||
throw std::runtime_error("CTransaction::GetChange() : value out of range");
|
||||
}
|
||||
return nChange;
|
||||
}
|
||||
|
||||
int64 GetValueOut() const
|
||||
{
|
||||
int64 nValueOut = 0;
|
||||
@ -1639,9 +1564,9 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
extern std::map<uint256, CTransaction> mapTransactions;
|
||||
extern std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
|
||||
extern std::map<uint160, std::vector<unsigned char> > mapPubKeys;
|
||||
extern CCriticalSection cs_mapKeys;
|
||||
extern CCriticalSection cs_mapPubKeys;
|
||||
|
||||
#endif
|
||||
|
@ -1117,7 +1117,7 @@ void MapPort(bool fMapPort)
|
||||
if (fUseUPnP != fMapPort)
|
||||
{
|
||||
fUseUPnP = fMapPort;
|
||||
CWalletDB().WriteSetting("fUseUPnP", fUseUPnP);
|
||||
WriteSetting("fUseUPnP", fUseUPnP);
|
||||
}
|
||||
if (fUseUPnP && vnThreadsRunning[5] < 1)
|
||||
{
|
||||
@ -1698,7 +1698,7 @@ void StartNode(void* parg)
|
||||
printf("Error: CreateThread(ThreadMessageHandler) failed\n");
|
||||
|
||||
// Generate coins in the background
|
||||
GenerateBitcoins(fGenerateBitcoins);
|
||||
GenerateBitcoins(fGenerateBitcoins, pwalletMain);
|
||||
}
|
||||
|
||||
bool StopNode()
|
||||
|
148
src/rpc.cpp
148
src/rpc.cpp
@ -264,14 +264,14 @@ Value setgenerate(const Array& params, bool fHelp)
|
||||
{
|
||||
int nGenProcLimit = params[1].get_int();
|
||||
fLimitProcessors = (nGenProcLimit != -1);
|
||||
CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors);
|
||||
WriteSetting("fLimitProcessors", fLimitProcessors);
|
||||
if (nGenProcLimit != -1)
|
||||
CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
|
||||
WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
|
||||
if (nGenProcLimit == 0)
|
||||
fGenerate = false;
|
||||
}
|
||||
|
||||
GenerateBitcoins(fGenerate);
|
||||
GenerateBitcoins(fGenerate, pwalletMain);
|
||||
return Value::null;
|
||||
}
|
||||
|
||||
@ -298,7 +298,7 @@ Value getinfo(const Array& params, bool fHelp)
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("version", (int)VERSION));
|
||||
obj.push_back(Pair("balance", ValueFromAmount(GetBalance())));
|
||||
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
||||
obj.push_back(Pair("blocks", (int)nBestHeight));
|
||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
|
||||
@ -307,7 +307,7 @@ Value getinfo(const Array& params, bool fHelp)
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||
obj.push_back(Pair("testnet", fTestNet));
|
||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime()));
|
||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
|
||||
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
|
||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||
return obj;
|
||||
@ -329,9 +329,9 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||
strAccount = AccountFromValue(params[0]);
|
||||
|
||||
// Generate a new key that is added to wallet
|
||||
string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
|
||||
string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
|
||||
|
||||
SetAddressBookName(strAddress, strAccount);
|
||||
pwalletMain->SetAddressBookName(strAddress, strAccount);
|
||||
return strAddress;
|
||||
}
|
||||
|
||||
@ -341,7 +341,7 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
|
||||
{
|
||||
string strAddress;
|
||||
|
||||
CWalletDB walletdb;
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
walletdb.TxnBegin();
|
||||
|
||||
CAccount account;
|
||||
@ -352,8 +352,8 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
|
||||
{
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
|
||||
it != mapWallet.end() && !account.vchPubKey.empty();
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
|
||||
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
|
||||
++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
@ -366,9 +366,9 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
|
||||
// Generate a new key
|
||||
if (account.vchPubKey.empty() || bForceNew)
|
||||
{
|
||||
account.vchPubKey = GetKeyFromKeyPool();
|
||||
account.vchPubKey = pwalletMain->GetKeyFromKeyPool();
|
||||
string strAddress = PubKeyToAddress(account.vchPubKey);
|
||||
SetAddressBookName(strAddress, strAccount);
|
||||
pwalletMain->SetAddressBookName(strAddress, strAccount);
|
||||
walletdb.WriteAccount(strAccount, account);
|
||||
}
|
||||
|
||||
@ -391,7 +391,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
|
||||
Value ret;
|
||||
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
ret = GetAccountAddress(strAccount);
|
||||
}
|
||||
@ -421,18 +421,18 @@ Value setaccount(const Array& params, bool fHelp)
|
||||
|
||||
// Detect when changing the account of an address that is the 'unused current key' of another account:
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
if (mapAddressBook.count(strAddress))
|
||||
if (pwalletMain->mapAddressBook.count(strAddress))
|
||||
{
|
||||
string strOldAccount = mapAddressBook[strAddress];
|
||||
string strOldAccount = pwalletMain->mapAddressBook[strAddress];
|
||||
if (strAddress == GetAccountAddress(strOldAccount))
|
||||
GetAccountAddress(strOldAccount, true);
|
||||
}
|
||||
}
|
||||
|
||||
SetAddressBookName(strAddress, strAccount);
|
||||
pwalletMain->SetAddressBookName(strAddress, strAccount);
|
||||
return Value::null;
|
||||
}
|
||||
|
||||
@ -447,10 +447,10 @@ Value getaccount(const Array& params, bool fHelp)
|
||||
string strAddress = params[0].get_str();
|
||||
|
||||
string strAccount;
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
map<string, string>::iterator mi = mapAddressBook.find(strAddress);
|
||||
if (mi != mapAddressBook.end() && !(*mi).second.empty())
|
||||
map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
|
||||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
|
||||
strAccount = (*mi).second;
|
||||
}
|
||||
return strAccount;
|
||||
@ -468,9 +468,9 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
|
||||
|
||||
// Find all addresses that have the given account
|
||||
Array ret;
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
|
||||
{
|
||||
const string& strAddress = item.first;
|
||||
const string& strName = item.second;
|
||||
@ -523,7 +523,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
{
|
||||
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
||||
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
||||
if (strError != "")
|
||||
throw JSONRPCError(-4, strError);
|
||||
}
|
||||
@ -544,7 +544,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
||||
CScript scriptPubKey;
|
||||
if (!scriptPubKey.SetBitcoinAddress(strAddress))
|
||||
throw JSONRPCError(-5, "Invalid bitcoin address");
|
||||
if (!IsMine(scriptPubKey))
|
||||
if (!IsMine(*pwalletMain,scriptPubKey))
|
||||
return (double)0.0;
|
||||
|
||||
// Minimum confirmations
|
||||
@ -554,9 +554,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
||||
|
||||
// Tally
|
||||
int64 nAmount = 0;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != 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())
|
||||
@ -575,9 +575,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
||||
|
||||
void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
|
||||
{
|
||||
const string& strAddress = item.first;
|
||||
const string& strName = item.second;
|
||||
@ -586,7 +586,7 @@ void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
|
||||
// We're only counting our own valid bitcoin addresses and not ip addresses
|
||||
CScript scriptPubKey;
|
||||
if (scriptPubKey.SetBitcoinAddress(strAddress))
|
||||
if (IsMine(scriptPubKey))
|
||||
if (IsMine(*pwalletMain,scriptPubKey))
|
||||
setPubKey.insert(scriptPubKey);
|
||||
}
|
||||
}
|
||||
@ -613,9 +613,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
||||
|
||||
// Tally
|
||||
int64 nAmount = 0;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != 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())
|
||||
@ -635,10 +635,10 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
||||
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
|
||||
{
|
||||
int64 nBalance = 0;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
// Tally wallet transactions
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
if (!wtx.IsFinal())
|
||||
@ -661,7 +661,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
|
||||
|
||||
int64 GetAccountBalance(const string& strAccount, int nMinDepth)
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
return GetAccountBalance(walletdb, strAccount, nMinDepth);
|
||||
}
|
||||
|
||||
@ -675,7 +675,7 @@ Value getbalance(const Array& params, bool fHelp)
|
||||
"If [account] is specified, returns the balance in the account.");
|
||||
|
||||
if (params.size() == 0)
|
||||
return ValueFromAmount(GetBalance());
|
||||
return ValueFromAmount(pwalletMain->GetBalance());
|
||||
|
||||
int nMinDepth = 1;
|
||||
if (params.size() > 1)
|
||||
@ -686,7 +686,7 @@ Value getbalance(const Array& params, bool fHelp)
|
||||
// (GetBalance() sums up all unspent TxOuts)
|
||||
// getbalance and getbalance '*' should always return the same number.
|
||||
int64 nBalance = 0;
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
if (!wtx.IsFinal())
|
||||
@ -734,9 +734,9 @@ Value movecmd(const Array& params, bool fHelp)
|
||||
if (params.size() > 4)
|
||||
strComment = params[4].get_str();
|
||||
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
walletdb.TxnBegin();
|
||||
|
||||
int64 nNow = GetAdjustedTime();
|
||||
@ -787,7 +787,7 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||
wtx.mapValue["to"] = params[5].get_str();
|
||||
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
// Check funds
|
||||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
||||
@ -795,7 +795,7 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||
throw JSONRPCError(-6, "Account has insufficient funds");
|
||||
|
||||
// Send
|
||||
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
||||
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
||||
if (strError != "")
|
||||
throw JSONRPCError(-4, strError);
|
||||
}
|
||||
@ -844,7 +844,7 @@ Value sendmany(const Array& params, bool fHelp)
|
||||
}
|
||||
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
// Check funds
|
||||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
||||
@ -852,16 +852,16 @@ Value sendmany(const Array& params, bool fHelp)
|
||||
throw JSONRPCError(-6, "Account has insufficient funds");
|
||||
|
||||
// Send
|
||||
CReserveKey keyChange;
|
||||
CReserveKey keyChange(pwalletMain);
|
||||
int64 nFeeRequired = 0;
|
||||
bool fCreated = CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
|
||||
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
|
||||
if (!fCreated)
|
||||
{
|
||||
if (totalAmount + nFeeRequired > GetBalance())
|
||||
if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
|
||||
throw JSONRPCError(-6, "Insufficient funds");
|
||||
throw JSONRPCError(-4, "Transaction creation failed");
|
||||
}
|
||||
if (!CommitTransaction(wtx, keyChange))
|
||||
if (!pwalletMain->CommitTransaction(wtx, keyChange))
|
||||
throw JSONRPCError(-4, "Transaction commit failed");
|
||||
}
|
||||
|
||||
@ -894,9 +894,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
|
||||
// Tally
|
||||
map<uint160, tallyitem> mapTally;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != 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())
|
||||
@ -923,9 +923,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
// Reply
|
||||
Array ret;
|
||||
map<string, tallyitem> mapAccountTally;
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
|
||||
{
|
||||
const string& strAddress = item.first;
|
||||
const string& strAccount = item.second;
|
||||
@ -1061,13 +1061,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
||||
|
||||
// Received
|
||||
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
|
||||
{
|
||||
string account;
|
||||
if (mapAddressBook.count(r.first))
|
||||
account = mapAddressBook[r.first];
|
||||
if (pwalletMain->mapAddressBook.count(r.first))
|
||||
account = pwalletMain->mapAddressBook[r.first];
|
||||
if (fAllAccounts || (account == strAccount))
|
||||
{
|
||||
Object entry;
|
||||
@ -1119,16 +1119,16 @@ Value listtransactions(const Array& params, bool fHelp)
|
||||
nFrom = params[2].get_int();
|
||||
|
||||
Array ret;
|
||||
CWalletDB walletdb;
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
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 = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
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)));
|
||||
@ -1180,16 +1180,16 @@ Value listaccounts(const Array& params, bool fHelp)
|
||||
nMinDepth = params[0].get_int();
|
||||
|
||||
map<string, int64> mapAccountBalances;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, mapAddressBook) {
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
|
||||
uint160 hash160;
|
||||
if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
|
||||
mapAccountBalances[entry.second] = 0;
|
||||
}
|
||||
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != 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;
|
||||
@ -1204,8 +1204,8 @@ Value listaccounts(const Array& params, bool fHelp)
|
||||
{
|
||||
mapAccountBalances[""] += nGeneratedMature;
|
||||
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
|
||||
if (mapAddressBook.count(r.first))
|
||||
mapAccountBalances[mapAddressBook[r.first]] += r.second;
|
||||
if (pwalletMain->mapAddressBook.count(r.first))
|
||||
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
|
||||
else
|
||||
mapAccountBalances[""] += r.second;
|
||||
}
|
||||
@ -1213,7 +1213,7 @@ Value listaccounts(const Array& params, bool fHelp)
|
||||
}
|
||||
|
||||
list<CAccountingEntry> acentries;
|
||||
CWalletDB().ListAccountCreditDebit("*", acentries);
|
||||
CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
|
||||
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
|
||||
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
|
||||
|
||||
@ -1235,11 +1235,11 @@ Value gettransaction(const Array& params, bool fHelp)
|
||||
hash.SetHex(params[0].get_str());
|
||||
|
||||
Object entry;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
if (!mapWallet.count(hash))
|
||||
if (!pwalletMain->mapWallet.count(hash))
|
||||
throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
|
||||
const CWalletTx& wtx = mapWallet[hash];
|
||||
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
|
||||
|
||||
int64 nCredit = wtx.GetCredit();
|
||||
int64 nDebit = wtx.GetDebit();
|
||||
@ -1250,10 +1250,10 @@ Value gettransaction(const Array& params, bool fHelp)
|
||||
if (wtx.IsFromMe())
|
||||
entry.push_back(Pair("fee", ValueFromAmount(nFee)));
|
||||
|
||||
WalletTxToJSON(mapWallet[hash], entry);
|
||||
WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
|
||||
|
||||
Array details;
|
||||
ListTransactions(mapWallet[hash], "*", 0, false, details);
|
||||
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
|
||||
entry.push_back(Pair("details", details));
|
||||
}
|
||||
|
||||
@ -1269,7 +1269,7 @@ Value backupwallet(const Array& params, bool fHelp)
|
||||
"Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
|
||||
|
||||
string strDest = params[0].get_str();
|
||||
BackupWallet(strDest);
|
||||
BackupWallet(*pwalletMain, strDest);
|
||||
|
||||
return Value::null;
|
||||
}
|
||||
@ -1295,10 +1295,10 @@ Value validateaddress(const Array& params, bool fHelp)
|
||||
string currentAddress = Hash160ToAddress(hash160);
|
||||
ret.push_back(Pair("address", currentAddress));
|
||||
ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
if (mapAddressBook.count(currentAddress))
|
||||
ret.push_back(Pair("account", mapAddressBook[currentAddress]));
|
||||
if (pwalletMain->mapAddressBook.count(currentAddress))
|
||||
ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress]));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -1325,7 +1325,7 @@ Value getwork(const Array& params, bool fHelp)
|
||||
|
||||
static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
|
||||
static vector<CBlock*> vNewBlock;
|
||||
static CReserveKey reservekey;
|
||||
static CReserveKey reservekey(pwalletMain);
|
||||
|
||||
if (params.size() == 0)
|
||||
{
|
||||
@ -1406,7 +1406,7 @@ Value getwork(const Array& params, bool fHelp)
|
||||
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
|
||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||
|
||||
return CheckWork(pblock, reservekey);
|
||||
return CheckWork(pblock, *pwalletMain, reservekey);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,7 +1021,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
|
||||
}
|
||||
|
||||
|
||||
bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
|
||||
bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
|
||||
{
|
||||
scriptSigRet.clear();
|
||||
|
||||
@ -1030,7 +1030,7 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
|
||||
return false;
|
||||
|
||||
// Compile solution
|
||||
CRITICAL_BLOCK(cs_mapKeys)
|
||||
CRITICAL_BLOCK(keystore.cs_mapKeys)
|
||||
{
|
||||
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
||||
{
|
||||
@ -1038,12 +1038,12 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
|
||||
{
|
||||
// Sign
|
||||
const valtype& vchPubKey = item.second;
|
||||
if (!mapKeys.count(vchPubKey))
|
||||
if (!keystore.HaveKey(vchPubKey))
|
||||
return false;
|
||||
if (hash != 0)
|
||||
{
|
||||
vector<unsigned char> vchSig;
|
||||
if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
|
||||
if (!CKey::Sign(keystore.GetPrivKey(vchPubKey), hash, vchSig))
|
||||
return false;
|
||||
vchSig.push_back((unsigned char)nHashType);
|
||||
scriptSigRet << vchSig;
|
||||
@ -1056,12 +1056,12 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
|
||||
if (mi == mapPubKeys.end())
|
||||
return false;
|
||||
const vector<unsigned char>& vchPubKey = (*mi).second;
|
||||
if (!mapKeys.count(vchPubKey))
|
||||
if (!keystore.HaveKey(vchPubKey))
|
||||
return false;
|
||||
if (hash != 0)
|
||||
{
|
||||
vector<unsigned char> vchSig;
|
||||
if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
|
||||
if (!CKey::Sign(keystore.GetPrivKey(vchPubKey), hash, vchSig))
|
||||
return false;
|
||||
vchSig.push_back((unsigned char)nHashType);
|
||||
scriptSigRet << vchSig << vchPubKey;
|
||||
@ -1085,14 +1085,14 @@ bool IsStandard(const CScript& scriptPubKey)
|
||||
}
|
||||
|
||||
|
||||
bool IsMine(const CScript& scriptPubKey)
|
||||
bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
|
||||
{
|
||||
CScript scriptSig;
|
||||
return Solver(scriptPubKey, 0, 0, scriptSig);
|
||||
return Solver(keystore, scriptPubKey, 0, 0, scriptSig);
|
||||
}
|
||||
|
||||
|
||||
bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet)
|
||||
bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* keystore, vector<unsigned char>& vchPubKeyRet)
|
||||
{
|
||||
vchPubKeyRet.clear();
|
||||
|
||||
@ -1100,7 +1100,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
|
||||
if (!Solver(scriptPubKey, vSolution))
|
||||
return false;
|
||||
|
||||
CRITICAL_BLOCK(cs_mapKeys)
|
||||
CRITICAL_BLOCK(cs_mapPubKeys)
|
||||
{
|
||||
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
||||
{
|
||||
@ -1116,7 +1116,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
|
||||
continue;
|
||||
vchPubKey = (*mi).second;
|
||||
}
|
||||
if (!fMineOnly || mapKeys.count(vchPubKey))
|
||||
if (keystore == NULL || keystore->HaveKey(vchPubKey))
|
||||
{
|
||||
vchPubKeyRet = vchPubKey;
|
||||
return true;
|
||||
@ -1160,7 +1160,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
|
||||
}
|
||||
|
||||
|
||||
bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
|
||||
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
CTxIn& txin = txTo.vin[nIn];
|
||||
@ -1171,7 +1171,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int
|
||||
// The checksig op will also drop the signatures from its hash.
|
||||
uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType);
|
||||
|
||||
if (!Solver(txout.scriptPubKey, hash, nHashType, txin.scriptSig))
|
||||
if (!Solver(keystore, txout.scriptPubKey, hash, nHashType, txin.scriptSig))
|
||||
return false;
|
||||
|
||||
txin.scriptSig = scriptPrereq + txin.scriptSig;
|
||||
@ -1199,10 +1199,5 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
|
||||
if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType))
|
||||
return false;
|
||||
|
||||
// Anytime a signature is successfully verified, it's proof the outpoint is spent,
|
||||
// so lets 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.
|
||||
WalletUpdateSpent(txin.prevout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -708,12 +708,11 @@ public:
|
||||
|
||||
|
||||
|
||||
uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
bool IsStandard(const CScript& scriptPubKey);
|
||||
bool IsMine(const CScript& scriptPubKey);
|
||||
bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, std::vector<unsigned char>& vchPubKeyRet);
|
||||
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
|
||||
bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* pkeystore, std::vector<unsigned char>& vchPubKeyRet);
|
||||
bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret);
|
||||
bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
|
||||
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
|
||||
bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
|
||||
|
||||
#endif
|
||||
|
186
src/ui.cpp
186
src/ui.cpp
@ -240,7 +240,7 @@ void SetDefaultReceivingAddress(const string& strAddress)
|
||||
return;
|
||||
if (!mapPubKeys.count(hash160))
|
||||
return;
|
||||
CWalletDB().WriteDefaultKey(mapPubKeys[hash160]);
|
||||
CWalletDB(pwalletMain->strWalletFile).WriteDefaultKey(mapPubKeys[hash160]);
|
||||
pframeMain->m_textCtrlAddress->SetValue(strAddress);
|
||||
}
|
||||
}
|
||||
@ -290,7 +290,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
|
||||
dResize = 1.22;
|
||||
SetSize(dResize * GetSize().GetWidth(), 1.15 * GetSize().GetHeight());
|
||||
#endif
|
||||
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
|
||||
m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + " ");
|
||||
m_listCtrl->SetFocus();
|
||||
ptaskbaricon = new CMyTaskBarIcon();
|
||||
#ifdef __WXMAC_OSX__
|
||||
@ -330,7 +330,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
|
||||
|
||||
// Fill your address text box
|
||||
vector<unsigned char> vchPubKey;
|
||||
if (CWalletDB("r").ReadDefaultKey(vchPubKey))
|
||||
if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey))
|
||||
m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey));
|
||||
|
||||
// Fill listctrl with wallet transactions
|
||||
@ -625,7 +625,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
{
|
||||
int64 nUnmatured = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
nUnmatured += txout.GetCredit();
|
||||
nUnmatured += pwalletMain->GetCredit(txout);
|
||||
if (wtx.IsInMainChain())
|
||||
{
|
||||
strDescription = strprintf(_("Generated (%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
|
||||
@ -661,19 +661,19 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
return false;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
{
|
||||
if (txout.IsMine())
|
||||
if (pwalletMain->IsMine(txout))
|
||||
{
|
||||
vector<unsigned char> vchPubKey;
|
||||
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
|
||||
if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
//strDescription += _("Received payment to ");
|
||||
//strDescription += _("Received with address ");
|
||||
strDescription += _("Received with: ");
|
||||
string strAddress = PubKeyToAddress(vchPubKey);
|
||||
map<string, string>::iterator mi = mapAddressBook.find(strAddress);
|
||||
if (mi != mapAddressBook.end() && !(*mi).second.empty())
|
||||
map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
|
||||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
|
||||
{
|
||||
string strLabel = (*mi).second;
|
||||
strDescription += strAddress.substr(0,12) + "... ";
|
||||
@ -703,11 +703,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
{
|
||||
bool fAllFromMe = true;
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
fAllFromMe = fAllFromMe && txin.IsMine();
|
||||
fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
|
||||
|
||||
bool fAllToMe = true;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
fAllToMe = fAllToMe && txout.IsMine();
|
||||
fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
|
||||
|
||||
if (fAllFromMe && fAllToMe)
|
||||
{
|
||||
@ -733,7 +733,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
|
||||
{
|
||||
const CTxOut& txout = wtx.vout[nOut];
|
||||
if (txout.IsMine())
|
||||
if (pwalletMain->IsMine(txout))
|
||||
continue;
|
||||
|
||||
string strAddress;
|
||||
@ -751,9 +751,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
}
|
||||
|
||||
string strDescription = _("To: ");
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
||||
strDescription += mapAddressBook[strAddress] + " ";
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
|
||||
strDescription += pwalletMain->mapAddressBook[strAddress] + " ";
|
||||
strDescription += strAddress;
|
||||
if (!mapValue["message"].empty())
|
||||
{
|
||||
@ -792,9 +792,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
//
|
||||
bool fAllMine = true;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
fAllMine = fAllMine && txout.IsMine();
|
||||
fAllMine = fAllMine && pwalletMain->IsMine(txout);
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
fAllMine = fAllMine && txin.IsMine();
|
||||
fAllMine = fAllMine && pwalletMain->IsMine(txin);
|
||||
|
||||
InsertLine(fNew, nIndex, hash, strSort, colour,
|
||||
strStatus,
|
||||
@ -821,16 +821,16 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
|
||||
// Collect list of wallet transactions and sort newest first
|
||||
bool fEntered = false;
|
||||
vector<pair<unsigned int, uint256> > vSorted;
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
printf("RefreshListCtrl starting\n");
|
||||
fEntered = true;
|
||||
fRefreshListCtrl = false;
|
||||
vWalletUpdated.clear();
|
||||
pwalletMain->vWalletUpdated.clear();
|
||||
|
||||
// Do the newest transactions first
|
||||
vSorted.reserve(mapWallet.size());
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
vSorted.reserve(pwalletMain->mapWallet.size());
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
unsigned int nTime = UINT_MAX - wtx.GetTxTime();
|
||||
@ -849,12 +849,12 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
|
||||
if (fShutdown)
|
||||
return;
|
||||
bool fEntered = false;
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
fEntered = true;
|
||||
uint256& hash = vSorted[i++].second;
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
|
||||
if (mi != mapWallet.end())
|
||||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
||||
if (mi != pwalletMain->mapWallet.end())
|
||||
InsertTransaction((*mi).second, true);
|
||||
}
|
||||
if (!fEntered || i == 100 || i % 500 == 0)
|
||||
@ -872,10 +872,10 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
|
||||
static int64 nLastTime;
|
||||
if (GetTime() > nLastTime + 30)
|
||||
{
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
nLastTime = GetTime();
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
CWalletTx& wtx = (*it).second;
|
||||
if (wtx.nTimeDisplayed && wtx.nTimeDisplayed != wtx.GetTxTime())
|
||||
@ -896,7 +896,7 @@ void CMainFrame::RefreshStatusColumn()
|
||||
if (nTop == nLastTop && pindexLastBest == pindexBest)
|
||||
return;
|
||||
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
int nStart = nTop;
|
||||
int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
|
||||
@ -916,8 +916,8 @@ void CMainFrame::RefreshStatusColumn()
|
||||
for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
|
||||
{
|
||||
uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
|
||||
if (mi == mapWallet.end())
|
||||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
||||
if (mi == pwalletMain->mapWallet.end())
|
||||
{
|
||||
printf("CMainFrame::RefreshStatusColumn() : tx not found in mapWallet\n");
|
||||
continue;
|
||||
@ -1014,41 +1014,41 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
|
||||
nLastRepaintTime = GetTimeMillis();
|
||||
|
||||
// Update listctrl contents
|
||||
if (!vWalletUpdated.empty())
|
||||
if (!pwalletMain->vWalletUpdated.empty())
|
||||
{
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
string strTop;
|
||||
if (m_listCtrl->GetItemCount())
|
||||
strTop = (string)m_listCtrl->GetItemText(0);
|
||||
BOOST_FOREACH(uint256 hash, vWalletUpdated)
|
||||
BOOST_FOREACH(uint256 hash, pwalletMain->vWalletUpdated)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
|
||||
if (mi != mapWallet.end())
|
||||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
||||
if (mi != pwalletMain->mapWallet.end())
|
||||
InsertTransaction((*mi).second, false);
|
||||
}
|
||||
vWalletUpdated.clear();
|
||||
pwalletMain->vWalletUpdated.clear();
|
||||
if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
|
||||
m_listCtrl->ScrollList(0, INT_MIN/2);
|
||||
}
|
||||
}
|
||||
|
||||
// Balance total
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
fPaintedBalance = true;
|
||||
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
|
||||
m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + " ");
|
||||
|
||||
// Count hidden and multi-line transactions
|
||||
nTransactionCount = 0;
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
CWalletTx& wtx = (*it).second;
|
||||
nTransactionCount += wtx.nLinesDisplayed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!vWalletUpdated.empty() || !fPaintedBalance)
|
||||
if (!pwalletMain->vWalletUpdated.empty() || !fPaintedBalance)
|
||||
nNeedRepaint++;
|
||||
|
||||
// Update status column of visible items only
|
||||
@ -1074,7 +1074,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
|
||||
m_statusBar->SetStatusText(strStatus, 2);
|
||||
|
||||
// Update receiving address
|
||||
string strDefaultAddress = PubKeyToAddress(vchDefaultKey);
|
||||
string strDefaultAddress = PubKeyToAddress(pwalletMain->vchDefaultKey);
|
||||
if (m_textCtrlAddress->GetValue() != strDefaultAddress)
|
||||
m_textCtrlAddress->SetValue(strDefaultAddress);
|
||||
}
|
||||
@ -1183,10 +1183,10 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
|
||||
string strName = dialog.GetValue();
|
||||
|
||||
// Generate new key
|
||||
string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
|
||||
string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
|
||||
|
||||
// Save
|
||||
SetAddressBookName(strAddress, strName);
|
||||
pwalletMain->SetAddressBookName(strAddress, strName);
|
||||
SetDefaultReceivingAddress(strAddress);
|
||||
}
|
||||
|
||||
@ -1204,10 +1204,10 @@ void CMainFrame::OnListItemActivated(wxListEvent& event)
|
||||
{
|
||||
uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
|
||||
CWalletTx wtx;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
|
||||
if (mi == mapWallet.end())
|
||||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
||||
if (mi == pwalletMain->mapWallet.end())
|
||||
{
|
||||
printf("CMainFrame::OnListItemActivated() : tx not found in mapWallet\n");
|
||||
return;
|
||||
@ -1235,7 +1235,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
#ifdef __WXMSW__
|
||||
SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
|
||||
#endif
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
string strHTML;
|
||||
strHTML.reserve(4000);
|
||||
@ -1285,19 +1285,19 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
// Credit
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
{
|
||||
if (txout.IsMine())
|
||||
if (pwalletMain->IsMine(txout))
|
||||
{
|
||||
vector<unsigned char> vchPubKey;
|
||||
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
|
||||
if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
|
||||
{
|
||||
string strAddress = PubKeyToAddress(vchPubKey);
|
||||
if (mapAddressBook.count(strAddress))
|
||||
if (pwalletMain->mapAddressBook.count(strAddress))
|
||||
{
|
||||
strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
|
||||
strHTML += _("<b>To:</b> ");
|
||||
strHTML += HtmlEscape(strAddress);
|
||||
if (!mapAddressBook[strAddress].empty())
|
||||
strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")";
|
||||
if (!pwalletMain->mapAddressBook[strAddress].empty())
|
||||
strHTML += _(" (yours, label: ") + pwalletMain->mapAddressBook[strAddress] + ")";
|
||||
else
|
||||
strHTML += _(" (yours)");
|
||||
strHTML += "<br>";
|
||||
@ -1319,8 +1319,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
// Online transaction
|
||||
strAddress = wtx.mapValue["to"];
|
||||
strHTML += _("<b>To:</b> ");
|
||||
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
||||
strHTML += mapAddressBook[strAddress] + " ";
|
||||
if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
|
||||
strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
|
||||
strHTML += HtmlEscape(strAddress) + "<br>";
|
||||
}
|
||||
|
||||
@ -1335,7 +1335,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
//
|
||||
int64 nUnmatured = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
nUnmatured += txout.GetCredit();
|
||||
nUnmatured += pwalletMain->GetCredit(txout);
|
||||
strHTML += _("<b>Credit:</b> ");
|
||||
if (wtx.IsInMainChain())
|
||||
strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
|
||||
@ -1354,11 +1354,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
{
|
||||
bool fAllFromMe = true;
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
fAllFromMe = fAllFromMe && txin.IsMine();
|
||||
fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
|
||||
|
||||
bool fAllToMe = true;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
fAllToMe = fAllToMe && txout.IsMine();
|
||||
fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
|
||||
|
||||
if (fAllFromMe)
|
||||
{
|
||||
@ -1367,7 +1367,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
//
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
{
|
||||
if (txout.IsMine())
|
||||
if (pwalletMain->IsMine(txout))
|
||||
continue;
|
||||
|
||||
if (wtx.mapValue["to"].empty())
|
||||
@ -1378,8 +1378,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
{
|
||||
string strAddress = Hash160ToAddress(hash160);
|
||||
strHTML += _("<b>To:</b> ");
|
||||
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
||||
strHTML += mapAddressBook[strAddress] + " ";
|
||||
if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
|
||||
strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
|
||||
strHTML += strAddress;
|
||||
strHTML += "<br>";
|
||||
}
|
||||
@ -1407,11 +1407,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
// Mixed debit transaction
|
||||
//
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
if (txin.IsMine())
|
||||
strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>";
|
||||
if (pwalletMain->IsMine(txin))
|
||||
strHTML += _("<b>Debit:</b> ") + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
if (txout.IsMine())
|
||||
strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>";
|
||||
if (pwalletMain->IsMine(txout))
|
||||
strHTML += _("<b>Credit:</b> ") + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1437,30 +1437,30 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
{
|
||||
strHTML += "<hr><br>debug print<br><br>";
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
if (txin.IsMine())
|
||||
strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
|
||||
if (pwalletMain->IsMine(txin))
|
||||
strHTML += "<b>Debit:</b> " + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
if (txout.IsMine())
|
||||
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
||||
if (pwalletMain->IsMine(txout))
|
||||
strHTML += "<b>Credit:</b> " + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
|
||||
|
||||
strHTML += "<br><b>Transaction:</b><br>";
|
||||
strHTML += HtmlEscape(wtx.ToString(), true);
|
||||
|
||||
strHTML += "<br><b>Inputs:</b><br>";
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
{
|
||||
COutPoint prevout = txin.prevout;
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
|
||||
if (mi != mapWallet.end())
|
||||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(prevout.hash);
|
||||
if (mi != pwalletMain->mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (prevout.n < prev.vout.size())
|
||||
{
|
||||
strHTML += HtmlEscape(prev.ToString(), true);
|
||||
strHTML += " " + FormatTxStatus(prev) + ", ";
|
||||
strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
|
||||
strHTML = strHTML + "IsMine=" + (pwalletMain->IsMine(prev.vout[prevout.n]) ? "true" : "false") + "<br>";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1751,7 +1751,7 @@ void COptionsDialog::OnButtonCancel(wxCommandEvent& event)
|
||||
|
||||
void COptionsDialog::OnButtonApply(wxCommandEvent& event)
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
|
||||
int64 nPrevTransactionFee = nTransactionFee;
|
||||
if (ParseMoney(m_textCtrlTransactionFee->GetValue(), nTransactionFee) && nTransactionFee != nPrevTransactionFee)
|
||||
@ -1928,12 +1928,12 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||
wxMessageBox(_("Error in amount "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
if (nValue > GetBalance())
|
||||
if (nValue > pwalletMain->GetBalance())
|
||||
{
|
||||
wxMessageBox(_("Amount exceeds your balance "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
if (nValue + nTransactionFee > GetBalance())
|
||||
if (nValue + nTransactionFee > pwalletMain->GetBalance())
|
||||
{
|
||||
wxMessageBox(string(_("Total exceeds your balance when the ")) + FormatMoney(nTransactionFee) + _(" transaction fee is included "), _("Send Coins"));
|
||||
return;
|
||||
@ -1951,7 +1951,7 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
|
||||
string strError = SendMoney(scriptPubKey, nValue, wtx, true);
|
||||
string strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
|
||||
if (strError == "")
|
||||
wxMessageBox(_("Payment sent "), _("Sending..."));
|
||||
else if (strError == "ABORTED")
|
||||
@ -1983,9 +1983,9 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||
return;
|
||||
}
|
||||
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
if (!mapAddressBook.count(strAddress))
|
||||
SetAddressBookName(strAddress, "");
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
if (!pwalletMain->mapAddressBook.count(strAddress))
|
||||
pwalletMain->SetAddressBookName(strAddress, "");
|
||||
|
||||
EndModal(true);
|
||||
}
|
||||
@ -2169,7 +2169,7 @@ void SendingDialogStartTransfer(void* parg)
|
||||
void CSendingDialog::StartTransfer()
|
||||
{
|
||||
// Make sure we have enough money
|
||||
if (nPrice + nTransactionFee > GetBalance())
|
||||
if (nPrice + nTransactionFee > pwalletMain->GetBalance())
|
||||
{
|
||||
Error(_("Insufficient funds"));
|
||||
return;
|
||||
@ -2240,16 +2240,16 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
||||
// Pay
|
||||
if (!Status(_("Creating transaction...")))
|
||||
return;
|
||||
if (nPrice + nTransactionFee > GetBalance())
|
||||
if (nPrice + nTransactionFee > pwalletMain->GetBalance())
|
||||
{
|
||||
Error(_("Insufficient funds"));
|
||||
return;
|
||||
}
|
||||
CReserveKey reservekey;
|
||||
CReserveKey reservekey(pwalletMain);
|
||||
int64 nFeeRequired;
|
||||
if (!CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
|
||||
if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
|
||||
{
|
||||
if (nPrice + nFeeRequired > GetBalance())
|
||||
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"));
|
||||
@ -2287,7 +2287,7 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
||||
return;
|
||||
|
||||
// Commit
|
||||
if (!CommitTransaction(wtx, reservekey))
|
||||
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;
|
||||
@ -2381,11 +2381,11 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
|
||||
m_listCtrlReceiving->SetFocus();
|
||||
|
||||
// Fill listctrl with address book data
|
||||
CRITICAL_BLOCK(cs_mapKeys)
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapKeys)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
{
|
||||
string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
|
||||
{
|
||||
string strAddress = item.first;
|
||||
string strName = item.second;
|
||||
@ -2444,7 +2444,7 @@ void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event)
|
||||
if (event.IsEditCancelled())
|
||||
return;
|
||||
string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
|
||||
SetAddressBookName(strAddress, string(event.GetText()));
|
||||
pwalletMain->SetAddressBookName(strAddress, string(event.GetText()));
|
||||
pframeMain->RefreshListCtrl();
|
||||
}
|
||||
|
||||
@ -2479,7 +2479,7 @@ void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event)
|
||||
if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
|
||||
{
|
||||
string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
|
||||
CWalletDB().EraseName(strAddress);
|
||||
CWalletDB(pwalletMain->strWalletFile).EraseName(strAddress);
|
||||
m_listCtrl->DeleteItem(nIndex);
|
||||
}
|
||||
}
|
||||
@ -2539,8 +2539,8 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event)
|
||||
|
||||
// Write back
|
||||
if (strAddress != strAddressOrg)
|
||||
CWalletDB().EraseName(strAddressOrg);
|
||||
SetAddressBookName(strAddress, strName);
|
||||
CWalletDB(pwalletMain->strWalletFile).EraseName(strAddressOrg);
|
||||
pwalletMain->SetAddressBookName(strAddress, strName);
|
||||
m_listCtrl->SetItem(nIndex, 1, strAddress);
|
||||
m_listCtrl->SetItemText(nIndex, strName);
|
||||
pframeMain->RefreshListCtrl();
|
||||
@ -2576,11 +2576,11 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
|
||||
strName = dialog.GetValue();
|
||||
|
||||
// Generate new key
|
||||
strAddress = PubKeyToAddress(GetKeyFromKeyPool());
|
||||
strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
|
||||
}
|
||||
|
||||
// Add to list and select it
|
||||
SetAddressBookName(strAddress, strName);
|
||||
pwalletMain->SetAddressBookName(strAddress, strName);
|
||||
int nIndex = InsertLine(m_listCtrl, strName, strAddress);
|
||||
SetSelection(m_listCtrl, nIndex);
|
||||
m_listCtrl->SetFocus();
|
||||
|
273
src/wallet.cpp
273
src/wallet.cpp
@ -15,29 +15,40 @@ using namespace std;
|
||||
// mapWallet
|
||||
//
|
||||
|
||||
void WalletUpdateSpent(const COutPoint& prevout)
|
||||
bool CWallet::AddKey(const CKey& key)
|
||||
{
|
||||
this->CKeyStore::AddKey(key);
|
||||
if (!fFileBacked)
|
||||
return true;
|
||||
return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
|
||||
}
|
||||
|
||||
void CWallet::WalletUpdateSpent(const CTransaction &tx)
|
||||
{
|
||||
// Anytime a signature is successfully verified, it's proof the outpoint is spent.
|
||||
// Update the wallet spent flag if it doesn't know due to wallet.dat being
|
||||
// restored from backup or the user making copies of wallet.dat.
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
|
||||
if (mi != mapWallet.end())
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
{
|
||||
CWalletTx& wtx = (*mi).second;
|
||||
if (!wtx.IsSpent(prevout.n) && wtx.vout[prevout.n].IsMine())
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
|
||||
wtx.MarkSpent(prevout.n);
|
||||
wtx.WriteToDisk();
|
||||
vWalletUpdated.push_back(prevout.hash);
|
||||
CWalletTx& wtx = (*mi).second;
|
||||
if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
|
||||
{
|
||||
printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
|
||||
wtx.MarkSpent(txin.prevout.n);
|
||||
wtx.WriteToDisk();
|
||||
vWalletUpdated.push_back(txin.prevout.hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AddToWallet(const CWalletTx& wtxIn)
|
||||
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
|
||||
{
|
||||
uint256 hash = wtxIn.GetHash();
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
@ -45,6 +56,7 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||
// Inserts only if not already there, returns tx inserted or tx found
|
||||
pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
|
||||
CWalletTx& wtx = (*ret.first).second;
|
||||
wtx.pwallet = this;
|
||||
bool fInsertedNew = ret.second;
|
||||
if (fInsertedNew)
|
||||
wtx.nTimeReceived = GetAdjustedTime();
|
||||
@ -87,7 +99,9 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||
{
|
||||
if (txout.scriptPubKey == scriptDefaultKey)
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
if (!fFileBacked)
|
||||
continue;
|
||||
CWalletDB walletdb(strWalletFile);
|
||||
vchDefaultKey = GetKeyFromKeyPool();
|
||||
walletdb.WriteDefaultKey(vchDefaultKey);
|
||||
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
|
||||
@ -96,6 +110,9 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||
|
||||
// Notify UI
|
||||
vWalletUpdated.push_back(hash);
|
||||
|
||||
// since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
|
||||
WalletUpdateSpent(wtx);
|
||||
}
|
||||
|
||||
// Refresh UI
|
||||
@ -103,60 +120,64 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
|
||||
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
|
||||
{
|
||||
uint256 hash = tx.GetHash();
|
||||
bool fExisted = mapWallet.count(hash);
|
||||
if (fExisted && !fUpdate) return false;
|
||||
if (fExisted || tx.IsMine() || tx.IsFromMe())
|
||||
if (fExisted || IsMine(tx) || IsFromMe(tx))
|
||||
{
|
||||
CWalletTx wtx(tx);
|
||||
CWalletTx wtx(this,tx);
|
||||
// Get merkle branch if transaction was found in a block
|
||||
if (pblock)
|
||||
wtx.SetMerkleBranch(pblock);
|
||||
return AddToWallet(wtx);
|
||||
}
|
||||
else
|
||||
WalletUpdateSpent(tx);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EraseFromWallet(uint256 hash)
|
||||
bool CWallet::EraseFromWallet(uint256 hash)
|
||||
{
|
||||
if (!fFileBacked)
|
||||
return false;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
if (mapWallet.erase(hash))
|
||||
CWalletDB().EraseTx(hash);
|
||||
CWalletDB(strWalletFile).EraseTx(hash);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CTxIn::IsMine() const
|
||||
bool CWallet::IsMine(const CTxIn &txin) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
|
||||
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (prevout.n < prev.vout.size())
|
||||
if (prev.vout[prevout.n].IsMine())
|
||||
if (txin.prevout.n < prev.vout.size())
|
||||
if (IsMine(prev.vout[txin.prevout.n]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int64 CTxIn::GetDebit() const
|
||||
int64 CWallet::GetDebit(const CTxIn &txin) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
|
||||
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (prevout.n < prev.vout.size())
|
||||
if (prev.vout[prevout.n].IsMine())
|
||||
return prev.vout[prevout.n].nValue;
|
||||
if (txin.prevout.n < prev.vout.size())
|
||||
if (IsMine(prev.vout[txin.prevout.n]))
|
||||
return prev.vout[txin.prevout.n].nValue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -184,31 +205,31 @@ int CWalletTx::GetRequestCount() const
|
||||
{
|
||||
// Returns -1 if it wasn't being tracked
|
||||
int nRequests = -1;
|
||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||
CRITICAL_BLOCK(pwallet->cs_mapRequestCount)
|
||||
{
|
||||
if (IsCoinBase())
|
||||
{
|
||||
// Generated block
|
||||
if (hashBlock != 0)
|
||||
{
|
||||
map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
|
||||
if (mi != mapRequestCount.end())
|
||||
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
nRequests = (*mi).second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Did anyone request this transaction?
|
||||
map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());
|
||||
if (mi != mapRequestCount.end())
|
||||
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
{
|
||||
nRequests = (*mi).second;
|
||||
|
||||
// How about the block it's in?
|
||||
if (nRequests == 0 && hashBlock != 0)
|
||||
{
|
||||
map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
|
||||
if (mi != mapRequestCount.end())
|
||||
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
nRequests = (*mi).second;
|
||||
else
|
||||
nRequests = 1; // If it's in someone else's block it must have got out
|
||||
@ -230,7 +251,7 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
|
||||
if (IsCoinBase())
|
||||
{
|
||||
if (GetBlocksToMaturity() > 0)
|
||||
nGeneratedImmature = CTransaction::GetCredit();
|
||||
nGeneratedImmature = pwallet->GetCredit(*this);
|
||||
else
|
||||
nGeneratedMature = GetCredit();
|
||||
return;
|
||||
@ -263,13 +284,13 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
|
||||
}
|
||||
|
||||
// Don't report 'change' txouts
|
||||
if (nDebit > 0 && txout.IsChange())
|
||||
if (nDebit > 0 && pwallet->IsChange(txout))
|
||||
continue;
|
||||
|
||||
if (nDebit > 0)
|
||||
listSent.push_back(make_pair(address, txout.nValue));
|
||||
|
||||
if (txout.IsMine())
|
||||
if (pwallet->IsMine(txout))
|
||||
listReceived.push_back(make_pair(address, txout.nValue));
|
||||
}
|
||||
|
||||
@ -295,16 +316,15 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
|
||||
nSent += s.second;
|
||||
nFee = allFee;
|
||||
}
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
CRITICAL_BLOCK(pwallet->cs_mapAddressBook)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listReceived)
|
||||
{
|
||||
if (mapAddressBook.count(r.first))
|
||||
if (pwallet->mapAddressBook.count(r.first))
|
||||
{
|
||||
if (mapAddressBook[r.first] == strAccount)
|
||||
{
|
||||
map<string, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
|
||||
if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
|
||||
nReceived += r.second;
|
||||
}
|
||||
}
|
||||
else if (strAccount.empty())
|
||||
{
|
||||
@ -326,7 +346,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
|
||||
vWorkQueue.push_back(txin.prevout.hash);
|
||||
|
||||
// This critsect is OK because txdb is already open
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(pwallet->cs_mapWallet)
|
||||
{
|
||||
map<uint256, const CMerkleTx*> mapWalletPrev;
|
||||
set<uint256> setAlreadyDone;
|
||||
@ -338,10 +358,11 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
|
||||
setAlreadyDone.insert(hash);
|
||||
|
||||
CMerkleTx tx;
|
||||
if (mapWallet.count(hash))
|
||||
map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
|
||||
if (mi != pwallet->mapWallet.end())
|
||||
{
|
||||
tx = mapWallet[hash];
|
||||
BOOST_FOREACH(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)
|
||||
tx = (*mi).second;
|
||||
BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
|
||||
mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
|
||||
}
|
||||
else if (mapWalletPrev.count(hash))
|
||||
@ -373,10 +394,10 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
|
||||
|
||||
bool CWalletTx::WriteToDisk()
|
||||
{
|
||||
return CWalletDB().WriteTx(GetHash(), *this);
|
||||
return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
|
||||
}
|
||||
|
||||
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||
int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@ -398,7 +419,7 @@ int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ReacceptWalletTransactions()
|
||||
void CWallet::ReacceptWalletTransactions()
|
||||
{
|
||||
CTxDB txdb("r");
|
||||
bool fRepeat = true;
|
||||
@ -426,7 +447,7 @@ void ReacceptWalletTransactions()
|
||||
{
|
||||
if (wtx.IsSpent(i))
|
||||
continue;
|
||||
if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
|
||||
if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
|
||||
{
|
||||
wtx.MarkSpent(i);
|
||||
fUpdated = true;
|
||||
@ -484,7 +505,7 @@ void CWalletTx::RelayWalletTransaction()
|
||||
RelayWalletTransaction(txdb);
|
||||
}
|
||||
|
||||
void ResendWalletTransactions()
|
||||
void CWallet::ResendWalletTransactions()
|
||||
{
|
||||
// Do this infrequently and randomly to avoid giving away
|
||||
// that these are our transactions.
|
||||
@ -536,16 +557,16 @@ void ResendWalletTransactions()
|
||||
//
|
||||
|
||||
|
||||
int64 GetBalance()
|
||||
int64 CWallet::GetBalance() const
|
||||
{
|
||||
int64 nStart = GetTimeMillis();
|
||||
|
||||
int64 nTotal = 0;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
CWalletTx* pcoin = &(*it).second;
|
||||
const CWalletTx* pcoin = &(*it).second;
|
||||
if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
|
||||
continue;
|
||||
nTotal += pcoin->GetAvailableCredit();
|
||||
@ -557,27 +578,27 @@ int64 GetBalance()
|
||||
}
|
||||
|
||||
|
||||
bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
|
||||
bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
|
||||
{
|
||||
setCoinsRet.clear();
|
||||
nValueRet = 0;
|
||||
|
||||
// List of values less than target
|
||||
pair<int64, pair<CWalletTx*,unsigned int> > coinLowestLarger;
|
||||
pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
|
||||
coinLowestLarger.first = INT64_MAX;
|
||||
coinLowestLarger.second.first = NULL;
|
||||
vector<pair<int64, pair<CWalletTx*,unsigned int> > > vValue;
|
||||
vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
|
||||
int64 nTotalLower = 0;
|
||||
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
vector<CWalletTx*> vCoins;
|
||||
vector<const CWalletTx*> vCoins;
|
||||
vCoins.reserve(mapWallet.size());
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
vCoins.push_back(&(*it).second);
|
||||
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
|
||||
|
||||
BOOST_FOREACH(CWalletTx* pcoin, vCoins)
|
||||
BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
|
||||
{
|
||||
if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
|
||||
continue;
|
||||
@ -591,7 +612,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
|
||||
|
||||
for (int i = 0; i < pcoin->vout.size(); i++)
|
||||
{
|
||||
if (pcoin->IsSpent(i) || !pcoin->vout[i].IsMine())
|
||||
if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
|
||||
continue;
|
||||
|
||||
int64 n = pcoin->vout[i].nValue;
|
||||
@ -599,7 +620,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
|
||||
if (n <= 0)
|
||||
continue;
|
||||
|
||||
pair<int64,pair<CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
|
||||
pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
|
||||
|
||||
if (n == nTargetValue)
|
||||
{
|
||||
@ -702,7 +723,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
|
||||
bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
|
||||
{
|
||||
return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
|
||||
SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
|
||||
@ -712,7 +733,7 @@ bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoi
|
||||
|
||||
|
||||
|
||||
bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
|
||||
bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
|
||||
{
|
||||
int64 nValue = 0;
|
||||
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
|
||||
@ -724,6 +745,8 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
|
||||
if (vecSend.empty() || nValue < 0)
|
||||
return false;
|
||||
|
||||
wtxNew.pwallet = this;
|
||||
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
{
|
||||
// txdb must be opened before the mapWallet lock
|
||||
@ -744,11 +767,11 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
|
||||
wtxNew.vout.push_back(CTxOut(s.second, s.first));
|
||||
|
||||
// Choose coins to use
|
||||
set<pair<CWalletTx*,unsigned int> > setCoins;
|
||||
set<pair<const CWalletTx*,unsigned int> > setCoins;
|
||||
int64 nValueIn = 0;
|
||||
if (!SelectCoins(nTotalValue, setCoins, nValueIn))
|
||||
return false;
|
||||
BOOST_FOREACH(PAIRTYPE(CWalletTx*, unsigned int) pcoin, setCoins)
|
||||
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
|
||||
{
|
||||
int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
|
||||
dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
|
||||
@ -784,13 +807,13 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
|
||||
reservekey.ReturnKey();
|
||||
|
||||
// Fill vin
|
||||
BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
|
||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
||||
wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
|
||||
|
||||
// Sign
|
||||
int nIn = 0;
|
||||
BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
|
||||
if (!SignSignature(*coin.first, wtxNew, nIn++))
|
||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
||||
if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
|
||||
return false;
|
||||
|
||||
// Limit size
|
||||
@ -820,7 +843,7 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
|
||||
bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
|
||||
{
|
||||
vector< pair<CScript, int64> > vecSend;
|
||||
vecSend.push_back(make_pair(scriptPubKey, nValue));
|
||||
@ -828,7 +851,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR
|
||||
}
|
||||
|
||||
// Call after CreateTransaction unless you want to abort
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
{
|
||||
@ -838,7 +861,7 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
// 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
|
||||
// maybe makes sense; please don't do it anywhere else.
|
||||
CWalletDB walletdb("r");
|
||||
CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
|
||||
|
||||
// Take key pair from key pool so it won't be used again
|
||||
reservekey.KeepKey();
|
||||
@ -851,11 +874,15 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
set<CWalletTx*> setCoins;
|
||||
BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
|
||||
{
|
||||
CWalletTx &pcoin = mapWallet[txin.prevout.hash];
|
||||
pcoin.MarkSpent(txin.prevout.n);
|
||||
pcoin.WriteToDisk();
|
||||
vWalletUpdated.push_back(pcoin.GetHash());
|
||||
CWalletTx &coin = mapWallet[txin.prevout.hash];
|
||||
coin.pwallet = this;
|
||||
coin.MarkSpent(txin.prevout.n);
|
||||
coin.WriteToDisk();
|
||||
vWalletUpdated.push_back(coin.GetHash());
|
||||
}
|
||||
|
||||
if (fFileBacked)
|
||||
delete pwalletdb;
|
||||
}
|
||||
|
||||
// Track how many getdata requests our transaction gets
|
||||
@ -879,9 +906,9 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
|
||||
|
||||
// requires cs_main lock
|
||||
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||
string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||
{
|
||||
CReserveKey reservekey;
|
||||
CReserveKey reservekey(this);
|
||||
int64 nFeeRequired;
|
||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||
{
|
||||
@ -907,7 +934,7 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
|
||||
|
||||
|
||||
// requires cs_main lock
|
||||
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||
string CWallet::SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||
{
|
||||
// Check amount
|
||||
if (nValue <= 0)
|
||||
@ -926,10 +953,12 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx
|
||||
|
||||
|
||||
|
||||
bool LoadWallet(bool& fFirstRunRet)
|
||||
bool CWallet::LoadWallet(bool& fFirstRunRet)
|
||||
{
|
||||
if (!fFileBacked)
|
||||
return false;
|
||||
fFirstRunRet = false;
|
||||
if (!CWalletDB("cr+").LoadWallet())
|
||||
if (!CWalletDB(strWalletFile,"cr+").LoadWallet(this))
|
||||
return false;
|
||||
fFirstRunRet = vchDefaultKey.empty();
|
||||
|
||||
@ -944,17 +973,52 @@ bool LoadWallet(bool& fFirstRunRet)
|
||||
// Create new keyUser and set as default key
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
CWalletDB walletdb;
|
||||
vchDefaultKey = GetKeyFromKeyPool();
|
||||
walletdb.WriteDefaultKey(vchDefaultKey);
|
||||
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
|
||||
if (!SetAddressBookName(PubKeyToAddress(vchDefaultKey), ""))
|
||||
return false;
|
||||
CWalletDB(strWalletFile).WriteDefaultKey(keyUser.GetPubKey());
|
||||
}
|
||||
|
||||
CreateThread(ThreadFlushWalletDB, NULL);
|
||||
CreateThread(ThreadFlushWalletDB, &strWalletFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
void CWallet::PrintWallet(const CBlock& block)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
if (mapWallet.count(block.vtx[0].GetHash()))
|
||||
{
|
||||
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
|
||||
printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
wtx = (*mi).second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
|
||||
{
|
||||
if (!pwallet->fFileBacked)
|
||||
return false;
|
||||
strWalletFileOut = pwallet->strWalletFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
{
|
||||
nIndex = -1;
|
||||
keypool.vchPubKey.clear();
|
||||
@ -962,6 +1026,8 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(cs_setKeyPool)
|
||||
{
|
||||
CWalletDB walletdb(strWalletFile);
|
||||
|
||||
// Top up key pool
|
||||
int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
|
||||
while (setKeyPool.size() < nTargetSize+1)
|
||||
@ -969,7 +1035,7 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
int64 nEnd = 1;
|
||||
if (!setKeyPool.empty())
|
||||
nEnd = *(--setKeyPool.end()) + 1;
|
||||
if (!Write(make_pair(string("pool"), nEnd), CKeyPool(GenerateNewKey())))
|
||||
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
|
||||
throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
|
||||
setKeyPool.insert(nEnd);
|
||||
printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
|
||||
@ -979,7 +1045,7 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
assert(!setKeyPool.empty());
|
||||
nIndex = *(setKeyPool.begin());
|
||||
setKeyPool.erase(setKeyPool.begin());
|
||||
if (!Read(make_pair(string("pool"), nIndex), keypool))
|
||||
if (!walletdb.ReadPool(nIndex, keypool))
|
||||
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
|
||||
if (!mapKeys.count(keypool.vchPubKey))
|
||||
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
|
||||
@ -988,18 +1054,21 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
}
|
||||
}
|
||||
|
||||
void CWalletDB::KeepKey(int64 nIndex)
|
||||
void CWallet::KeepKey(int64 nIndex)
|
||||
{
|
||||
// Remove from key pool
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
if (fFileBacked)
|
||||
{
|
||||
Erase(make_pair(string("pool"), nIndex));
|
||||
CWalletDB walletdb(strWalletFile);
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
{
|
||||
walletdb.ErasePool(nIndex);
|
||||
}
|
||||
}
|
||||
printf("keypool keep %"PRI64d"\n", nIndex);
|
||||
}
|
||||
|
||||
void CWalletDB::ReturnKey(int64 nIndex)
|
||||
void CWallet::ReturnKey(int64 nIndex)
|
||||
{
|
||||
// Return to key pool
|
||||
CRITICAL_BLOCK(cs_setKeyPool)
|
||||
@ -1007,32 +1076,30 @@ void CWalletDB::ReturnKey(int64 nIndex)
|
||||
printf("keypool return %"PRI64d"\n", nIndex);
|
||||
}
|
||||
|
||||
vector<unsigned char> GetKeyFromKeyPool()
|
||||
vector<unsigned char> CWallet::GetKeyFromKeyPool()
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
int64 nIndex = 0;
|
||||
CKeyPool keypool;
|
||||
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
walletdb.KeepKey(nIndex);
|
||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
KeepKey(nIndex);
|
||||
return keypool.vchPubKey;
|
||||
}
|
||||
|
||||
int64 GetOldestKeyPoolTime()
|
||||
int64 CWallet::GetOldestKeyPoolTime()
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
int64 nIndex = 0;
|
||||
CKeyPool keypool;
|
||||
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
walletdb.ReturnKey(nIndex);
|
||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
ReturnKey(nIndex);
|
||||
return keypool.nTime;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CReserveKey::GetReservedKey()
|
||||
vector<unsigned char> CReserveKey::GetReservedKey()
|
||||
{
|
||||
if (nIndex == -1)
|
||||
{
|
||||
CKeyPool keypool;
|
||||
CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
vchPubKey = keypool.vchPubKey;
|
||||
}
|
||||
assert(!vchPubKey.empty());
|
||||
@ -1042,7 +1109,7 @@ std::vector<unsigned char> CReserveKey::GetReservedKey()
|
||||
void CReserveKey::KeepKey()
|
||||
{
|
||||
if (nIndex != -1)
|
||||
CWalletDB().KeepKey(nIndex);
|
||||
pwallet->KeepKey(nIndex);
|
||||
nIndex = -1;
|
||||
vchPubKey.clear();
|
||||
}
|
||||
@ -1050,7 +1117,7 @@ void CReserveKey::KeepKey()
|
||||
void CReserveKey::ReturnKey()
|
||||
{
|
||||
if (nIndex != -1)
|
||||
CWalletDB::ReturnKey(nIndex);
|
||||
pwallet->ReturnKey(nIndex);
|
||||
nIndex = -1;
|
||||
vchPubKey.clear();
|
||||
}
|
||||
|
248
src/wallet.h
248
src/wallet.h
@ -5,40 +5,205 @@
|
||||
#define BITCOIN_WALLET_H
|
||||
|
||||
#include "bignum.h"
|
||||
#include "key.h"
|
||||
#include "script.h"
|
||||
|
||||
class CWalletTx;
|
||||
class CReserveKey;
|
||||
class CWalletDB;
|
||||
|
||||
extern std::map<uint256, CWalletTx> mapWallet;
|
||||
extern std::vector<uint256> vWalletUpdated;
|
||||
extern CCriticalSection cs_mapWallet;
|
||||
class CWallet : public CKeyStore
|
||||
{
|
||||
private:
|
||||
bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, 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;
|
||||
|
||||
extern std::map<uint256, int> mapRequestCount;
|
||||
extern CCriticalSection cs_mapRequestCount;
|
||||
|
||||
extern std::map<std::string, std::string> mapAddressBook;
|
||||
extern CCriticalSection cs_mapAddressBook;
|
||||
public:
|
||||
bool fFileBacked;
|
||||
std::string strWalletFile;
|
||||
|
||||
extern std::vector<unsigned char> vchDefaultKey;
|
||||
extern CKey keyUser;
|
||||
std::set<int64> setKeyPool;
|
||||
CCriticalSection cs_setKeyPool;
|
||||
|
||||
bool AddToWallet(const CWalletTx& wtxIn);
|
||||
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
|
||||
bool EraseFromWallet(uint256 hash);
|
||||
void WalletUpdateSpent(const COutPoint& prevout);
|
||||
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
|
||||
void ReacceptWalletTransactions();
|
||||
void ResendWalletTransactions();
|
||||
int64 GetBalance();
|
||||
bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
||||
bool BroadcastTransaction(CWalletTx& wtxNew);
|
||||
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||
std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||
CWallet()
|
||||
{
|
||||
fFileBacked = false;
|
||||
}
|
||||
CWallet(std::string strWalletFileIn)
|
||||
{
|
||||
strWalletFile = strWalletFileIn;
|
||||
fFileBacked = true;
|
||||
}
|
||||
|
||||
mutable CCriticalSection cs_mapWallet;
|
||||
std::map<uint256, CWalletTx> mapWallet;
|
||||
std::vector<uint256> vWalletUpdated;
|
||||
|
||||
std::map<uint256, int> mapRequestCount;
|
||||
mutable CCriticalSection cs_mapRequestCount;
|
||||
|
||||
std::map<std::string, std::string> mapAddressBook;
|
||||
mutable CCriticalSection cs_mapAddressBook;
|
||||
|
||||
std::vector<unsigned char> vchDefaultKey;
|
||||
CKey keyUser;
|
||||
|
||||
bool AddKey(const CKey& key);
|
||||
bool AddToWallet(const CWalletTx& wtxIn);
|
||||
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
|
||||
bool EraseFromWallet(uint256 hash);
|
||||
void WalletUpdateSpent(const CTransaction& prevout);
|
||||
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
|
||||
void ReacceptWalletTransactions();
|
||||
void ResendWalletTransactions();
|
||||
int64 GetBalance() const;
|
||||
bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
||||
bool BroadcastTransaction(CWalletTx& wtxNew);
|
||||
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||
std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||
|
||||
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
|
||||
void KeepKey(int64 nIndex);
|
||||
void ReturnKey(int64 nIndex);
|
||||
std::vector<unsigned char> GetKeyFromKeyPool();
|
||||
int64 GetOldestKeyPoolTime();
|
||||
|
||||
bool IsMine(const CTxIn& txin) const;
|
||||
int64 GetDebit(const CTxIn& txin) const;
|
||||
bool IsMine(const CTxOut& txout) const
|
||||
{
|
||||
return ::IsMine(*this, txout.scriptPubKey);
|
||||
}
|
||||
int64 GetCredit(const CTxOut& txout) const
|
||||
{
|
||||
if (!MoneyRange(txout.nValue))
|
||||
throw std::runtime_error("CWallet::GetCredit() : value out of range");
|
||||
return (IsMine(txout) ? txout.nValue : 0);
|
||||
}
|
||||
bool IsChange(const CTxOut& txout) const
|
||||
{
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
if (ExtractPubKey(txout.scriptPubKey, this, vchPubKey))
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
int64 GetChange(const CTxOut& txout) const
|
||||
{
|
||||
if (!MoneyRange(txout.nValue))
|
||||
throw std::runtime_error("CWallet::GetChange() : value out of range");
|
||||
if (IsChange(txout) ? txout.nValue : 0);
|
||||
}
|
||||
bool IsMine(const CTransaction& tx) const
|
||||
{
|
||||
BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
||||
if (IsMine(txout))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool IsFromMe(const CTransaction& tx) const
|
||||
{
|
||||
return (GetDebit(tx) > 0);
|
||||
}
|
||||
int64 GetDebit(const CTransaction& tx) const
|
||||
{
|
||||
int64 nDebit = 0;
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
{
|
||||
nDebit += GetDebit(txin);
|
||||
if (!MoneyRange(nDebit))
|
||||
throw std::runtime_error("CWallet::GetDebit() : value out of range");
|
||||
}
|
||||
return nDebit;
|
||||
}
|
||||
int64 GetCredit(const CTransaction& tx) const
|
||||
{
|
||||
int64 nCredit = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
||||
{
|
||||
nCredit += GetCredit(txout);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error("CWallet::GetCredit() : value out of range");
|
||||
}
|
||||
return nCredit;
|
||||
}
|
||||
int64 GetChange(const CTransaction& tx) const
|
||||
{
|
||||
int64 nChange = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
||||
{
|
||||
nChange += GetChange(txout);
|
||||
if (!MoneyRange(nChange))
|
||||
throw std::runtime_error("CWallet::GetChange() : value out of range");
|
||||
}
|
||||
return nChange;
|
||||
}
|
||||
void SetBestChain(const CBlockLocator& loc)
|
||||
{
|
||||
CWalletDB walletdb(strWalletFile);
|
||||
walletdb.WriteBestBlock(loc);
|
||||
}
|
||||
|
||||
bool LoadWallet(bool& fFirstRunRet);
|
||||
// bool BackupWallet(const std::string& strDest);
|
||||
|
||||
bool SetAddressBookName(const std::string& strAddress, const std::string& strName)
|
||||
{
|
||||
if (!fFileBacked)
|
||||
return false;
|
||||
return CWalletDB(strWalletFile).WriteName(strAddress, strName);
|
||||
}
|
||||
|
||||
void UpdatedTransaction(const uint256 &hashTx)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
vWalletUpdated.push_back(hashTx);
|
||||
}
|
||||
|
||||
void PrintWallet(const CBlock& block);
|
||||
|
||||
void Inventory(const uint256 &hash)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||
{
|
||||
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
|
||||
if (mi != mapRequestCount.end())
|
||||
(*mi).second++;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CReserveKey
|
||||
{
|
||||
protected:
|
||||
CWallet* pwallet;
|
||||
int64 nIndex;
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
public:
|
||||
CReserveKey(CWallet* pwalletIn)
|
||||
{
|
||||
nIndex = -1;
|
||||
pwallet = pwalletIn;
|
||||
}
|
||||
|
||||
~CReserveKey()
|
||||
{
|
||||
if (!fShutdown)
|
||||
ReturnKey();
|
||||
}
|
||||
|
||||
void ReturnKey();
|
||||
std::vector<unsigned char> GetReservedKey();
|
||||
void KeepKey();
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
@ -49,6 +214,8 @@ std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWal
|
||||
class CWalletTx : public CMerkleTx
|
||||
{
|
||||
public:
|
||||
const CWallet* pwallet;
|
||||
|
||||
std::vector<CMerkleTx> vtxPrev;
|
||||
std::map<std::string, std::string> mapValue;
|
||||
std::vector<std::pair<std::string, std::string> > vOrderForm;
|
||||
@ -73,24 +240,29 @@ public:
|
||||
mutable int nLinesDisplayed;
|
||||
mutable char fConfirmedDisplayed;
|
||||
|
||||
|
||||
CWalletTx()
|
||||
{
|
||||
Init();
|
||||
Init(NULL);
|
||||
}
|
||||
|
||||
CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
|
||||
CWalletTx(const CWallet* pwalletIn)
|
||||
{
|
||||
Init();
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
|
||||
CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
|
||||
{
|
||||
Init();
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
void Init()
|
||||
CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
void Init(const CWallet* pwalletIn)
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
vtxPrev.clear();
|
||||
mapValue.clear();
|
||||
vOrderForm.clear();
|
||||
@ -116,7 +288,7 @@ public:
|
||||
(
|
||||
CWalletTx* pthis = const_cast<CWalletTx*>(this);
|
||||
if (fRead)
|
||||
pthis->Init();
|
||||
pthis->Init(NULL);
|
||||
char fSpent = false;
|
||||
|
||||
if (!fRead)
|
||||
@ -213,7 +385,7 @@ public:
|
||||
return 0;
|
||||
if (fDebitCached)
|
||||
return nDebitCached;
|
||||
nDebitCached = CTransaction::GetDebit();
|
||||
nDebitCached = pwallet->GetDebit(*this);
|
||||
fDebitCached = true;
|
||||
return nDebitCached;
|
||||
}
|
||||
@ -227,7 +399,7 @@ public:
|
||||
// GetBalance can assume transactions in mapWallet won't change
|
||||
if (fUseCache && fCreditCached)
|
||||
return nCreditCached;
|
||||
nCreditCached = CTransaction::GetCredit();
|
||||
nCreditCached = pwallet->GetCredit(*this);
|
||||
fCreditCached = true;
|
||||
return nCreditCached;
|
||||
}
|
||||
@ -247,7 +419,7 @@ public:
|
||||
if (!IsSpent(i))
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
nCredit += txout.GetCredit();
|
||||
nCredit += pwallet->GetCredit(txout);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
|
||||
}
|
||||
@ -263,7 +435,7 @@ public:
|
||||
{
|
||||
if (fChangeCached)
|
||||
return nChangeCached;
|
||||
nChangeCached = CTransaction::GetChange();
|
||||
nChangeCached = pwallet->GetChange(*this);
|
||||
fChangeCached = true;
|
||||
return nChangeCached;
|
||||
}
|
||||
@ -271,7 +443,7 @@ public:
|
||||
void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<std::string /* address */, int64> >& listReceived,
|
||||
std::list<std::pair<std::string /* address */, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
|
||||
|
||||
void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived,
|
||||
void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived,
|
||||
int64& nSent, int64& nFee) const;
|
||||
|
||||
bool IsFromMe() const
|
||||
@ -303,7 +475,7 @@ public:
|
||||
return false;
|
||||
if (ptx->GetDepthInMainChain() >= 1)
|
||||
continue;
|
||||
if (!ptx->IsFromMe())
|
||||
if (!pwallet->IsFromMe(*ptx))
|
||||
return false;
|
||||
|
||||
if (mapPrev.empty())
|
||||
@ -438,4 +610,6 @@ public:
|
||||
)
|
||||
};
|
||||
|
||||
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user