Browse Source

update core to d0d80170a2 (CWallet class)

miguelfreitas
Wladimir J. van der Laan 14 years ago
parent
commit
e8ef3da713
  1. 8
      bitcoin-qt.pro
  2. 168
      src/db.cpp
  3. 118
      src/db.h
  4. 2
      src/headers.h
  5. 37
      src/init.cpp
  6. 2
      src/init.h
  7. 33
      src/keystore.cpp
  8. 30
      src/keystore.h
  9. 1443
      src/main.cpp
  10. 567
      src/main.h
  11. 4
      src/net.cpp
  12. 2
      src/noui.h
  13. 76
      src/qt/addresstablemodel.cpp
  14. 4
      src/qt/addresstablemodel.h
  15. 7
      src/qt/bitcoin.cpp
  16. 2
      src/qt/bitcoingui.cpp
  17. 29
      src/qt/clientmodel.cpp
  18. 5
      src/qt/clientmodel.h
  19. 11
      src/qt/optionsmodel.cpp
  20. 7
      src/qt/optionsmodel.h
  21. 54
      src/qt/transactiondesc.cpp
  22. 3
      src/qt/transactiondesc.h
  23. 21
      src/qt/transactionrecord.cpp
  24. 4
      src/qt/transactionrecord.h
  25. 58
      src/qt/transactiontablemodel.cpp
  26. 5
      src/qt/transactiontablemodel.h
  27. 1
      src/qtui.h
  28. 149
      src/rpc.cpp
  29. 33
      src/script.cpp
  30. 8
      src/script.h
  31. 2
      src/util.cpp
  32. 4
      src/util.h
  33. 1176
      src/wallet.cpp
  34. 611
      src/wallet.h

8
bitcoin-qt.pro

@ -70,7 +70,9 @@ HEADERS += src/qt/bitcoingui.h \
src/qtui.h \ src/qtui.h \
src/qt/transactiondesc.h \ src/qt/transactiondesc.h \
src/qt/transactiondescdialog.h \ src/qt/transactiondescdialog.h \
src/qt/bitcoinamountfield.h src/qt/bitcoinamountfield.h \
src/wallet.h \
src/keystore.h
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactiontablemodel.cpp \ src/qt/transactiontablemodel.cpp \
src/qt/addresstablemodel.cpp \ src/qt/addresstablemodel.cpp \
@ -101,7 +103,9 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactiondesc.cpp \ src/qt/transactiondesc.cpp \
src/qt/transactiondescdialog.cpp \ src/qt/transactiondescdialog.cpp \
src/qt/bitcoinstrings.cpp \ src/qt/bitcoinstrings.cpp \
src/qt/bitcoinamountfield.cpp src/qt/bitcoinamountfield.cpp \
src/wallet.cpp \
src/keystore.cpp
RESOURCES += \ RESOURCES += \
src/qt/bitcoin.qrc src/qt/bitcoin.qrc

168
src/db.cpp

@ -5,14 +5,12 @@
#include "headers.h" #include "headers.h"
#include "db.h" #include "db.h"
#include "net.h" #include "net.h"
#include <boost/filesystem/operations.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
using namespace std; using namespace std;
using namespace boost; using namespace boost;
void ThreadFlushWalletDB(void* parg);
unsigned int nWalletDBUpdated; unsigned int nWalletDBUpdated;
uint64 nAccountingEntryNumber = 0; uint64 nAccountingEntryNumber = 0;
@ -151,7 +149,7 @@ void CDB::Close()
--mapFileUseCount[strFile]; --mapFileUseCount[strFile];
} }
void CloseDb(const string& strFile) void static CloseDb(const string& strFile)
{ {
CRITICAL_BLOCK(cs_db) CRITICAL_BLOCK(cs_db)
{ {
@ -360,7 +358,7 @@ bool CTxDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork)
return Write(string("bnBestInvalidWork"), bnBestInvalidWork); return Write(string("bnBestInvalidWork"), bnBestInvalidWork);
} }
CBlockIndex* InsertBlockIndex(uint256 hash) CBlockIndex static * InsertBlockIndex(uint256 hash)
{ {
if (hash == 0) if (hash == 0)
return NULL; return NULL;
@ -585,8 +583,19 @@ bool LoadAddresses()
// CWalletDB // CWalletDB
// //
static set<int64> setKeyPool; bool CWalletDB::WriteName(const string& strAddress, const string& strName)
static CCriticalSection cs_setKeyPool; {
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) bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
{ {
@ -661,9 +670,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; int nFileVersion = 0;
vector<uint256> vWalletUpgrade; vector<uint256> vWalletUpgrade;
@ -675,8 +684,8 @@ bool CWalletDB::LoadWallet()
#endif #endif
//// todo: shouldn't we catch exceptions and try to recover and continue? //// todo: shouldn't we catch exceptions and try to recover and continue?
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwallet->cs_mapWallet)
CRITICAL_BLOCK(cs_mapKeys) CRITICAL_BLOCK(pwallet->cs_mapKeys)
{ {
// Get cursor // Get cursor
Dbc* pcursor = GetCursor(); Dbc* pcursor = GetCursor();
@ -703,14 +712,15 @@ bool CWalletDB::LoadWallet()
{ {
string strAddress; string strAddress;
ssKey >> strAddress; ssKey >> strAddress;
ssValue >> mapAddressBook[strAddress]; ssValue >> pwallet->mapAddressBook[strAddress];
} }
else if (strType == "tx") else if (strType == "tx")
{ {
uint256 hash; uint256 hash;
ssKey >> hash; ssKey >> hash;
CWalletTx& wtx = mapWallet[hash]; CWalletTx& wtx = pwallet->mapWallet[hash];
ssValue >> wtx; ssValue >> wtx;
wtx.pwallet = pwallet;
if (wtx.GetHash() != hash) if (wtx.GetHash() != hash)
printf("Error in wallet.dat, hash mismatch\n"); printf("Error in wallet.dat, hash mismatch\n");
@ -761,18 +771,18 @@ bool CWalletDB::LoadWallet()
else else
ssValue >> wkey; ssValue >> wkey;
mapKeys[vchPubKey] = wkey.vchPrivKey; pwallet->mapKeys[vchPubKey] = wkey.vchPrivKey;
mapPubKeys[Hash160(vchPubKey)] = vchPubKey; mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
} }
else if (strType == "defaultkey") else if (strType == "defaultkey")
{ {
ssValue >> vchDefaultKey; ssValue >> pwallet->vchDefaultKey;
} }
else if (strType == "pool") else if (strType == "pool")
{ {
int64 nIndex; int64 nIndex;
ssKey >> nIndex; ssKey >> nIndex;
setKeyPool.insert(nIndex); pwallet->setKeyPool.insert(nIndex);
} }
else if (strType == "version") else if (strType == "version")
{ {
@ -804,7 +814,7 @@ bool CWalletDB::LoadWallet()
} }
BOOST_FOREACH(uint256 hash, vWalletUpgrade) BOOST_FOREACH(uint256 hash, vWalletUpgrade)
WriteTx(hash, mapWallet[hash]); WriteTx(hash, pwallet->mapWallet[hash]);
printf("nFileVersion = %d\n", nFileVersion); printf("nFileVersion = %d\n", nFileVersion);
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins); printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
@ -832,36 +842,9 @@ bool CWalletDB::LoadWallet()
return true; return true;
} }
bool LoadWallet(bool& fFirstRunRet)
{
fFirstRunRet = false;
if (!CWalletDB("cr+").LoadWallet())
return false;
fFirstRunRet = vchDefaultKey.empty();
if (mapKeys.count(vchDefaultKey))
{
// Set keyUser
keyUser.SetPubKey(vchDefaultKey);
keyUser.SetPrivKey(mapKeys[vchDefaultKey]);
}
else
{
// Create new keyUser and set as default key
RandAddSeedPerfmon();
CWalletDB walletdb;
vchDefaultKey = GetKeyFromKeyPool();
walletdb.WriteDefaultKey(vchDefaultKey);
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
}
CreateThread(ThreadFlushWalletDB, NULL);
return true;
}
void ThreadFlushWalletDB(void* parg) void ThreadFlushWalletDB(void* parg)
{ {
const string& strFile = ((const string*)parg)[0];
static bool fOneThread; static bool fOneThread;
if (fOneThread) if (fOneThread)
return; return;
@ -897,7 +880,6 @@ void ThreadFlushWalletDB(void* parg)
if (nRefCount == 0 && !fShutdown) if (nRefCount == 0 && !fShutdown)
{ {
string strFile = "wallet.dat";
map<string, int>::iterator mi = mapFileUseCount.find(strFile); map<string, int>::iterator mi = mapFileUseCount.find(strFile);
if (mi != mapFileUseCount.end()) if (mi != mapFileUseCount.end())
{ {
@ -920,26 +902,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) while (!fShutdown)
{ {
CRITICAL_BLOCK(cs_db) CRITICAL_BLOCK(cs_db)
{ {
const string strFile = "wallet.dat"; if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
{ {
// Flush log data to the dat file // Flush log data to the dat file
CloseDb(strFile); CloseDb(wallet.strWalletFile);
dbenv.txn_checkpoint(0, 0, 0); dbenv.txn_checkpoint(0, 0, 0);
dbenv.lsn_reset(strFile.c_str(), 0); dbenv.lsn_reset(wallet.strWalletFile.c_str(), 0);
mapFileUseCount.erase(strFile); mapFileUseCount.erase(wallet.strWalletFile);
// Copy wallet.dat // Copy wallet.dat
filesystem::path pathSrc(GetDataDir() + "/" + strFile); filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
filesystem::path pathDest(strDest); filesystem::path pathDest(strDest);
if (filesystem::is_directory(pathDest)) if (filesystem::is_directory(pathDest))
pathDest = pathDest / strFile; pathDest = pathDest / wallet.strWalletFile;
#if BOOST_VERSION >= 104000 #if BOOST_VERSION >= 104000
filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
#else #else
@ -947,83 +930,10 @@ void BackupWallet(const string& strDest)
#endif #endif
printf("copied wallet.dat to %s\n", pathDest.string().c_str()); printf("copied wallet.dat to %s\n", pathDest.string().c_str());
return; return true;
} }
} }
Sleep(100); Sleep(100);
} }
} return false;
void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{
nIndex = -1;
keypool.vchPubKey.clear();
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_setKeyPool)
{
// Top up key pool
int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
while (setKeyPool.size() < nTargetSize+1)
{
int64 nEnd = 1;
if (!setKeyPool.empty())
nEnd = *(--setKeyPool.end()) + 1;
if (!Write(make_pair(string("pool"), 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());
}
// Get the oldest key
assert(!setKeyPool.empty());
nIndex = *(setKeyPool.begin());
setKeyPool.erase(setKeyPool.begin());
if (!Read(make_pair(string("pool"), nIndex), keypool))
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
if (!mapKeys.count(keypool.vchPubKey))
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
assert(!keypool.vchPubKey.empty());
printf("keypool reserve %"PRI64d"\n", nIndex);
}
}
void CWalletDB::KeepKey(int64 nIndex)
{
// Remove from key pool
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
{
Erase(make_pair(string("pool"), nIndex));
}
printf("keypool keep %"PRI64d"\n", nIndex);
}
void CWalletDB::ReturnKey(int64 nIndex)
{
// Return to key pool
CRITICAL_BLOCK(cs_setKeyPool)
setKeyPool.insert(nIndex);
printf("keypool return %"PRI64d"\n", nIndex);
}
vector<unsigned char> GetKeyFromKeyPool()
{
CWalletDB walletdb;
int64 nIndex = 0;
CKeyPool keypool;
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
walletdb.KeepKey(nIndex);
return keypool.vchPubKey;
}
int64 GetOldestKeyPoolTime()
{
CWalletDB walletdb;
int64 nIndex = 0;
CKeyPool keypool;
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
walletdb.ReturnKey(nIndex);
return keypool.nTime;
} }

118
src/db.h

@ -12,33 +12,25 @@
#include <db_cxx.h> #include <db_cxx.h>
class CTransaction;
class CTxIndex; class CTxIndex;
class CDiskBlockIndex; class CDiskBlockIndex;
class CDiskTxPos; class CDiskTxPos;
class COutPoint; class COutPoint;
class CUser;
class CReview;
class CAddress; class CAddress;
class CWalletTx; class CWalletTx;
class CWallet;
class CAccount; class CAccount;
class CAccountingEntry; class CAccountingEntry;
class CBlockLocator; class CBlockLocator;
extern std::map<std::string, std::string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;
extern std::vector<unsigned char> vchDefaultKey;
extern bool fClient;
extern int nBestHeight;
extern unsigned int nWalletDBUpdated; extern unsigned int nWalletDBUpdated;
extern DbEnv dbenv; extern DbEnv dbenv;
extern void DBFlush(bool fShutdown); extern void DBFlush(bool fShutdown);
extern std::vector<unsigned char> GetKeyFromKeyPool(); void ThreadFlushWalletDB(void* parg);
extern int64 GetOldestKeyPoolTime(); bool BackupWallet(const CWallet& wallet, const std::string& strDest);
@ -321,9 +313,6 @@ bool LoadAddresses();
class CKeyPool class CKeyPool
{ {
public: public:
@ -356,7 +345,7 @@ public:
class CWalletDB : public CDB class CWalletDB : public CDB
{ {
public: public:
CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode) CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
{ {
} }
private: private:
@ -369,23 +358,9 @@ public:
return Read(std::make_pair(std::string("name"), strAddress), strName); return Read(std::make_pair(std::string("name"), strAddress), strName);
} }
bool WriteName(const std::string& strAddress, const std::string& 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 EraseName(const std::string& strAddress) 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 ReadTx(uint256 hash, CWalletTx& wtx) bool ReadTx(uint256 hash, CWalletTx& wtx)
{ {
@ -435,11 +410,27 @@ public:
bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey) bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
{ {
vchDefaultKey = vchPubKey;
nWalletDBUpdated++; nWalletDBUpdated++;
return Write(std::string("defaultkey"), vchPubKey); 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> template<typename T>
bool ReadSetting(const std::string& strKey, T& value) bool ReadSetting(const std::string& strKey, T& value)
{ {
@ -459,68 +450,7 @@ public:
int64 GetAccountCreditDebit(const std::string& strAccount); int64 GetAccountCreditDebit(const std::string& strAccount);
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries); void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
bool LoadWallet(); bool LoadWallet(CWallet* pwallet);
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()
{
if (nIndex == -1)
{
CKeyPool keypool;
CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
vchPubKey = keypool.vchPubKey;
}
assert(!vchPubKey.empty());
return vchPubKey;
}
void KeepKey()
{
if (nIndex != -1)
CWalletDB().KeepKey(nIndex);
nIndex = -1;
vchPubKey.clear();
}
void ReturnKey()
{
if (nIndex != -1)
CWalletDB::ReturnKey(nIndex);
nIndex = -1;
vchPubKey.clear();
}
}; };
#endif #endif

2
src/headers.h

@ -91,10 +91,8 @@
#include "serialize.h" #include "serialize.h"
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"
#include "key.h"
#include "bignum.h" #include "bignum.h"
#include "base58.h" #include "base58.h"
#include "script.h"
#include "main.h" #include "main.h"
#ifdef GUI #ifdef GUI
#include "uibase.h" #include "uibase.h"

37
src/init.cpp

@ -7,13 +7,15 @@
#include "net.h" #include "net.h"
#include "init.h" #include "init.h"
#include "strlcpy.h" #include "strlcpy.h"
#include <boost/filesystem/operations.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/interprocess/sync/file_lock.hpp> #include <boost/interprocess/sync/file_lock.hpp>
using namespace std; using namespace std;
using namespace boost; using namespace boost;
CWallet* pwalletMain;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// Shutdown // Shutdown
@ -46,6 +48,8 @@ void Shutdown(void* parg)
StopNode(); StopNode();
DBFlush(true); DBFlush(true);
boost::filesystem::remove(GetPidFile()); boost::filesystem::remove(GetPidFile());
UnregisterWallet(pwalletMain);
delete pwalletMain;
CreateThread(ExitTimeout, NULL); CreateThread(ExitTimeout, NULL);
Sleep(50); Sleep(50);
printf("Bitcoin exiting\n\n"); printf("Bitcoin exiting\n\n");
@ -137,10 +141,19 @@ bool AppInit2(int argc, char* argv[])
if (mapArgs.count("-datadir")) if (mapArgs.count("-datadir"))
{ {
filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]); if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"])))
strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir)); {
filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
}
else
{
fprintf(stderr, "Error: Specified directory does not exist\n");
Shutdown(NULL);
}
} }
ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
if (mapArgs.count("-?") || mapArgs.count("--help")) if (mapArgs.count("-?") || mapArgs.count("--help"))
@ -372,16 +385,19 @@ bool AppInit2(int argc, char* argv[])
printf("Loading wallet...\n"); printf("Loading wallet...\n");
nStart = GetTimeMillis(); nStart = GetTimeMillis();
bool fFirstRun; bool fFirstRun;
if (!LoadWallet(fFirstRun)) pwalletMain = new CWallet("wallet.dat");
if (!pwalletMain->LoadWallet(fFirstRun))
strErrors += _("Error loading wallet.dat \n"); strErrors += _("Error loading wallet.dat \n");
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart); printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
RegisterWallet(pwalletMain);
CBlockIndex *pindexRescan = pindexBest; CBlockIndex *pindexRescan = pindexBest;
if (GetBoolArg("-rescan")) if (GetBoolArg("-rescan"))
pindexRescan = pindexGenesisBlock; pindexRescan = pindexGenesisBlock;
else else
{ {
CWalletDB walletdb; CWalletDB walletdb("wallet.dat");
CBlockLocator locator; CBlockLocator locator;
if (walletdb.ReadBestBlock(locator)) if (walletdb.ReadBestBlock(locator))
pindexRescan = locator.GetBlockIndex(); pindexRescan = locator.GetBlockIndex();
@ -390,7 +406,7 @@ bool AppInit2(int argc, char* argv[])
{ {
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
nStart = GetTimeMillis(); nStart = GetTimeMillis();
ScanForWalletTransactions(pindexRescan, true); pwalletMain->ScanForWalletTransactions(pindexRescan, true);
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
} }
@ -399,10 +415,11 @@ bool AppInit2(int argc, char* argv[])
//// debug print //// debug print
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size()); printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
printf("nBestHeight = %d\n", nBestHeight); 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("mapPubKeys.size() = %d\n", mapPubKeys.size());
printf("mapWallet.size() = %d\n", mapWallet.size()); printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
printf("mapAddressBook.size() = %d\n", mapAddressBook.size()); printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
if (!strErrors.empty()) if (!strErrors.empty())
{ {
@ -411,7 +428,7 @@ bool AppInit2(int argc, char* argv[])
} }
// Add wallet transactions that aren't already in a block to mapTransactions // Add wallet transactions that aren't already in a block to mapTransactions
ReacceptWalletTransactions(); pwalletMain->ReacceptWalletTransactions();
// //
// Parameters // Parameters

2
src/init.h

@ -4,6 +4,8 @@
#ifndef BITCOIN_INIT_H #ifndef BITCOIN_INIT_H
#define BITCOIN_INIT_H #define BITCOIN_INIT_H
extern CWallet* pwalletMain;
void Shutdown(void* parg); void Shutdown(void* parg);
bool AppInit(int argc, char* argv[]); bool AppInit(int argc, char* argv[]);
bool AppInit2(int argc, char* argv[]); bool AppInit2(int argc, char* argv[]);

33
src/keystore.cpp

@ -0,0 +1,33 @@
// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
#include "db.h"
//////////////////////////////////////////////////////////////////////////////
//
// mapKeys
//
std::vector<unsigned char> CKeyStore::GenerateNewKey()
{
RandAddSeedPerfmon();
CKey key;
key.MakeNewKey();
if (!AddKey(key))
throw std::runtime_error("GenerateNewKey() : AddKey failed");
return key.GetPubKey();
}
bool CKeyStore::AddKey(const CKey& key)
{
CRITICAL_BLOCK(cs_mapKeys)
{
mapKeys[key.GetPubKey()] = key.GetPrivKey();
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
}
}

30
src/keystore.h

@ -0,0 +1,30 @@
// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KEYSTORE_H
#define BITCOIN_KEYSTORE_H
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);
}
bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CPrivKey& keyOut) const
{
std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey);
if (mi != mapKeys.end())
{
keyOut = (*mi).second;
return true;
}
return false;
}
std::vector<unsigned char> GenerateNewKey();
};
#endif

1443
src/main.cpp

File diff suppressed because it is too large Load Diff

567
src/main.h

@ -7,22 +7,18 @@
#include "bignum.h" #include "bignum.h"
#include "net.h" #include "net.h"
#include "key.h" #include "key.h"
#include "db.h"
#include "script.h" #include "script.h"
#include "db.h"
#include <list> #include <list>
class COutPoint;
class CInPoint;
class CDiskTxPos;
class CCoinBase;
class CTxIn;
class CTxOut;
class CTransaction;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
class CWalletTx; class CWalletTx;
class CWallet;
class CKeyItem; class CKeyItem;
class CReserveKey;
class CWalletDB;
class CMessageHeader; class CMessageHeader;
class CAddress; class CAddress;
@ -63,13 +59,11 @@ extern CBigNum bnBestInvalidWork;
extern uint256 hashBestChain; extern uint256 hashBestChain;
extern CBlockIndex* pindexBest; extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated; extern unsigned int nTransactionsUpdated;
extern std::map<uint256, int> mapRequestCount;
extern CCriticalSection cs_mapRequestCount;
extern std::map<std::string, std::string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;
extern std::vector<unsigned char> vchDefaultKey;
extern double dHashesPerSec; extern double dHashesPerSec;
extern int64 nHPSTimerStart; extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
extern CCriticalSection cs_setpwalletRegistered;
extern std::set<CWallet*> setpwalletRegistered;
// Settings // Settings
extern int fGenerateBitcoins; extern int fGenerateBitcoins;
@ -89,34 +83,20 @@ class CReserveKey;
class CTxDB; class CTxDB;
class CTxIndex; class CTxIndex;
void RegisterWallet(CWallet* pwalletIn);
void UnregisterWallet(CWallet* pwalletIn);
bool CheckDiskSpace(uint64 nAdditionalBytes=0); bool CheckDiskSpace(uint64 nAdditionalBytes=0);
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
FILE* AppendBlockFile(unsigned int& nFileRet); FILE* AppendBlockFile(unsigned int& nFileRet);
bool AddKey(const CKey& key);
std::vector<unsigned char> GenerateNewKey();
bool AddToWallet(const CWalletTx& wtxIn);
void WalletUpdateSpent(const COutPoint& prevout);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
bool LoadBlockIndex(bool fAllowNew=true); bool LoadBlockIndex(bool fAllowNew=true);
void PrintBlockTree(); void PrintBlockTree();
bool ProcessMessages(CNode* pfrom); bool ProcessMessages(CNode* pfrom);
bool ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv);
bool SendMessages(CNode* pto, bool fSendTrickle); bool SendMessages(CNode* pto, bool fSendTrickle);
int64 GetBalance(); void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
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 GenerateBitcoins(bool fGenerate);
void ThreadBitcoinMiner(void* parg);
CBlock* CreateNewBlock(CReserveKey& reservekey); CBlock* CreateNewBlock(CReserveKey& reservekey);
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime); void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime);
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1); void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
bool CheckWork(CBlock* pblock, CReserveKey& reservekey); bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
void BitcoinMiner();
bool CheckProofOfWork(uint256 hash, unsigned int nBits); bool CheckProofOfWork(uint256 hash, unsigned int nBits);
int GetTotalBlocksEstimate(); int GetTotalBlocksEstimate();
bool IsInitialBlockDownload(); bool IsInitialBlockDownload();
@ -133,6 +113,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 class CDiskTxPos
{ {
public: public:
@ -315,9 +312,6 @@ public:
{ {
printf("%s\n", ToString().c_str()); printf("%s\n", ToString().c_str());
} }
bool IsMine() const;
int64 GetDebit() const;
}; };
@ -366,36 +360,6 @@ public:
return SerializeHash(*this); 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) friend bool operator==(const CTxOut& a, const CTxOut& b)
{ {
return (a.nValue == b.nValue && return (a.nValue == b.nValue &&
@ -540,57 +504,6 @@ public:
return true; 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 GetValueOut() const
{ {
int64 nValueOut = 0; int64 nValueOut = 0;
@ -722,11 +635,7 @@ public:
bool ClientConnectInputs(); bool ClientConnectInputs();
bool CheckTransaction() const; bool CheckTransaction() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL); bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL) bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
{
CTxDB txdb("r");
return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
}
protected: protected:
bool AddToMemoryPoolUnchecked(); bool AddToMemoryPoolUnchecked();
public: public:
@ -785,307 +694,7 @@ public:
bool IsInMainChain() const { return GetDepthInMainChain() > 0; } bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const; int GetBlocksToMaturity() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true); bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
bool AcceptToMemoryPool() { CTxDB txdb("r"); return AcceptToMemoryPool(txdb); } bool AcceptToMemoryPool();
};
//
// A transaction with a bunch of additional info that only the owner cares
// about. It includes any unrecorded transactions needed to link it back
// to the block chain.
//
class CWalletTx : public CMerkleTx
{
public:
std::vector<CMerkleTx> vtxPrev;
std::map<std::string, std::string> mapValue;
std::vector<std::pair<std::string, std::string> > vOrderForm;
unsigned int fTimeReceivedIsTxTime;
unsigned int nTimeReceived; // time received by this node
char fFromMe;
std::string strFromAccount;
std::vector<char> vfSpent;
// memory only
mutable char fDebitCached;
mutable char fCreditCached;
mutable char fAvailableCreditCached;
mutable char fChangeCached;
mutable int64 nDebitCached;
mutable int64 nCreditCached;
mutable int64 nAvailableCreditCached;
mutable int64 nChangeCached;
// memory only UI hints
mutable unsigned int nTimeDisplayed;
mutable int nLinesDisplayed;
mutable char fConfirmedDisplayed;
CWalletTx()
{
Init();
}
CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
{
Init();
}
CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
{
Init();
}
void Init()
{
vtxPrev.clear();
mapValue.clear();
vOrderForm.clear();
fTimeReceivedIsTxTime = false;
nTimeReceived = 0;
fFromMe = false;
strFromAccount.clear();
vfSpent.clear();
fDebitCached = false;
fCreditCached = false;
fAvailableCreditCached = false;
fChangeCached = false;
nDebitCached = 0;
nCreditCached = 0;
nAvailableCreditCached = 0;
nChangeCached = 0;
nTimeDisplayed = 0;
nLinesDisplayed = 0;
fConfirmedDisplayed = false;
}
IMPLEMENT_SERIALIZE
(
CWalletTx* pthis = const_cast<CWalletTx*>(this);
if (fRead)
pthis->Init();
char fSpent = false;
if (!fRead)
{
pthis->mapValue["fromaccount"] = pthis->strFromAccount;
std::string str;
BOOST_FOREACH(char f, vfSpent)
{
str += (f ? '1' : '0');
if (f)
fSpent = true;
}
pthis->mapValue["spent"] = str;
}
nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
READWRITE(vtxPrev);
READWRITE(mapValue);
READWRITE(vOrderForm);
READWRITE(fTimeReceivedIsTxTime);
READWRITE(nTimeReceived);
READWRITE(fFromMe);
READWRITE(fSpent);
if (fRead)
{
pthis->strFromAccount = pthis->mapValue["fromaccount"];
if (mapValue.count("spent"))
BOOST_FOREACH(char c, pthis->mapValue["spent"])
pthis->vfSpent.push_back(c != '0');
else
pthis->vfSpent.assign(vout.size(), fSpent);
}
pthis->mapValue.erase("fromaccount");
pthis->mapValue.erase("version");
pthis->mapValue.erase("spent");
)
// marks certain txout's as spent
// returns true if any update took place
bool UpdateSpent(const std::vector<char>& vfNewSpent)
{
bool fReturn = false;
for (int i=0; i < vfNewSpent.size(); i++)
{
if (i == vfSpent.size())
break;
if (vfNewSpent[i] && !vfSpent[i])
{
vfSpent[i] = true;
fReturn = true;
fAvailableCreditCached = false;
}
}
return fReturn;
}
void MarkDirty()
{
fCreditCached = false;
fAvailableCreditCached = false;
fDebitCached = false;
fChangeCached = false;
}
void MarkSpent(unsigned int nOut)
{
if (nOut >= vout.size())
throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
vfSpent.resize(vout.size());
if (!vfSpent[nOut])
{
vfSpent[nOut] = true;
fAvailableCreditCached = false;
}
}
bool IsSpent(unsigned int nOut) const
{
if (nOut >= vout.size())
throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
if (nOut >= vfSpent.size())
return false;
return (!!vfSpent[nOut]);
}
int64 GetDebit() const
{
if (vin.empty())
return 0;
if (fDebitCached)
return nDebitCached;
nDebitCached = CTransaction::GetDebit();
fDebitCached = true;
return nDebitCached;
}
int64 GetCredit(bool fUseCache=true) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
// GetBalance can assume transactions in mapWallet won't change
if (fUseCache && fCreditCached)
return nCreditCached;
nCreditCached = CTransaction::GetCredit();
fCreditCached = true;
return nCreditCached;
}
int64 GetAvailableCredit(bool fUseCache=true) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
if (fUseCache && fAvailableCreditCached)
return nAvailableCreditCached;
int64 nCredit = 0;
for (int i = 0; i < vout.size(); i++)
{
if (!IsSpent(i))
{
const CTxOut &txout = vout[i];
nCredit += txout.GetCredit();
if (!MoneyRange(nCredit))
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
}
}
nAvailableCreditCached = nCredit;
fAvailableCreditCached = true;
return nCredit;
}
int64 GetChange() const
{
if (fChangeCached)
return nChangeCached;
nChangeCached = CTransaction::GetChange();
fChangeCached = true;
return nChangeCached;
}
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,
int64& nSent, int64& nFee) const;
bool IsFromMe() const
{
return (GetDebit() > 0);
}
bool IsConfirmed() const
{
// Quick answer in most cases
if (!IsFinal())
return false;
if (GetDepthInMainChain() >= 1)
return true;
if (!IsFromMe()) // using wtx's cached debit
return false;
// If no confirmations but it's from us, we can still
// consider it confirmed if all dependencies are confirmed
std::map<uint256, const CMerkleTx*> mapPrev;
std::vector<const CMerkleTx*> vWorkQueue;
vWorkQueue.reserve(vtxPrev.size()+1);
vWorkQueue.push_back(this);
for (int i = 0; i < vWorkQueue.size(); i++)
{
const CMerkleTx* ptx = vWorkQueue[i];
if (!ptx->IsFinal())
return false;
if (ptx->GetDepthInMainChain() >= 1)
continue;
if (!ptx->IsFromMe())
return false;
if (mapPrev.empty())
BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
mapPrev[tx.GetHash()] = &tx;
BOOST_FOREACH(const CTxIn& txin, ptx->vin)
{
if (!mapPrev.count(txin.prevout.hash))
return false;
vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
}
}
return true;
}
bool WriteToDisk()
{
return CWalletDB().WriteTx(GetHash(), *this);
}
int64 GetTxTime() const;
int GetRequestCount() const;
void AddSupportingTransactions(CTxDB& txdb);
bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }
void RelayWalletTransaction(CTxDB& txdb);
void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }
}; };
@ -1745,114 +1354,6 @@ public:
//
// Private key that includes an expiration date in case it never gets used.
//
class CWalletKey
{
public:
CPrivKey vchPrivKey;
int64 nTimeCreated;
int64 nTimeExpires;
std::string strComment;
//// todo: add something to note what created it (user, getnewaddress, change)
//// maybe should have a map<string, string> property map
CWalletKey(int64 nExpires=0)
{
nTimeCreated = (nExpires ? GetTime() : 0);
nTimeExpires = nExpires;
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPrivKey);
READWRITE(nTimeCreated);
READWRITE(nTimeExpires);
READWRITE(strComment);
)
};
//
// Account information.
// Stored in wallet with key "acc"+string account name
//
class CAccount
{
public:
std::vector<unsigned char> vchPubKey;
CAccount()
{
SetNull();
}
void SetNull()
{
vchPubKey.clear();
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPubKey);
)
};
//
// Internal transfers.
// Database key is acentry<account><counter>
//
class CAccountingEntry
{
public:
std::string strAccount;
int64 nCreditDebit;
int64 nTime;
std::string strOtherAccount;
std::string strComment;
CAccountingEntry()
{
SetNull();
}
void SetNull()
{
nCreditDebit = 0;
nTime = 0;
strAccount.clear();
strOtherAccount.clear();
strComment.clear();
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
// Note: strAccount is serialized as part of the key, not here.
READWRITE(nCreditDebit);
READWRITE(nTime);
READWRITE(strOtherAccount);
READWRITE(strComment);
)
};
@ -2064,13 +1565,9 @@ public:
extern std::map<uint256, CTransaction> mapTransactions; extern std::map<uint256, CTransaction> mapTransactions;
extern std::map<uint256, CWalletTx> mapWallet;
extern std::vector<uint256> vWalletUpdated;
extern CCriticalSection cs_mapWallet;
extern std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
extern std::map<uint160, std::vector<unsigned char> > mapPubKeys; extern std::map<uint160, std::vector<unsigned char> > mapPubKeys;
extern CCriticalSection cs_mapKeys; extern CCriticalSection cs_mapPubKeys;
extern CKey keyUser;
#endif #endif

4
src/net.cpp

@ -1117,7 +1117,7 @@ void MapPort(bool fMapPort)
if (fUseUPnP != fMapPort) if (fUseUPnP != fMapPort)
{ {
fUseUPnP = fMapPort; fUseUPnP = fMapPort;
CWalletDB().WriteSetting("fUseUPnP", fUseUPnP); WriteSetting("fUseUPnP", fUseUPnP);
} }
if (fUseUPnP && vnThreadsRunning[5] < 1) if (fUseUPnP && vnThreadsRunning[5] < 1)
{ {
@ -1698,7 +1698,7 @@ void StartNode(void* parg)
printf("Error: CreateThread(ThreadMessageHandler) failed\n"); printf("Error: CreateThread(ThreadMessageHandler) failed\n");
// Generate coins in the background // Generate coins in the background
GenerateBitcoins(fGenerateBitcoins); GenerateBitcoins(fGenerateBitcoins, pwalletMain);
} }
bool StopNode() bool StopNode()

2
src/noui.h

@ -5,6 +5,8 @@
#define BITCOIN_NOUI_H #define BITCOIN_NOUI_H
#include <string> #include <string>
#include <boost/function.hpp>
#include "wallet.h"
typedef void wxWindow; typedef void wxWindow;
#define wxYES 0x00000002 #define wxYES 0x00000002

76
src/qt/addresstablemodel.cpp

@ -1,6 +1,7 @@
#include "addresstablemodel.h" #include "addresstablemodel.h"
#include "guiutil.h" #include "guiutil.h"
#include "main.h"
#include "headers.h"
#include <QFont> #include <QFont>
#include <QColor> #include <QColor>
@ -22,31 +23,25 @@ struct AddressTableEntry
AddressTableEntry() {} AddressTableEntry() {}
AddressTableEntry(Type type, const QString &label, const QString &address): AddressTableEntry(Type type, const QString &label, const QString &address):
type(type), label(label), address(address) {} type(type), label(label), address(address) {}
bool isDefaultAddress() const
{
std::vector<unsigned char> vchPubKey;
if (CWalletDB("r").ReadDefaultKey(vchPubKey))
{
return address == QString::fromStdString(PubKeyToAddress(vchPubKey));
}
return false;
}
}; };
// Private implementation // Private implementation
struct AddressTablePriv struct AddressTablePriv
{ {
CWallet *wallet;
QList<AddressTableEntry> cachedAddressTable; QList<AddressTableEntry> cachedAddressTable;
AddressTablePriv(CWallet *wallet):
wallet(wallet) {}
void refreshAddressTable() void refreshAddressTable()
{ {
cachedAddressTable.clear(); cachedAddressTable.clear();
CRITICAL_BLOCK(cs_mapKeys) CRITICAL_BLOCK(wallet->cs_mapKeys)
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(wallet->cs_mapAddressBook)
{ {
BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, mapAddressBook) BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, wallet->mapAddressBook)
{ {
std::string strAddress = item.first; std::string strAddress = item.first;
std::string strName = item.second; std::string strName = item.second;
@ -75,13 +70,18 @@ struct AddressTablePriv
return 0; return 0;
} }
} }
bool isDefaultAddress(const AddressTableEntry *rec)
{
return rec->address == QString::fromStdString(wallet->GetDefaultAddress());
}
}; };
AddressTableModel::AddressTableModel(QObject *parent) : AddressTableModel::AddressTableModel(CWallet *wallet, QObject *parent) :
QAbstractTableModel(parent),priv(0) QAbstractTableModel(parent),wallet(wallet),priv(0)
{ {
columns << tr("Label") << tr("Address"); columns << tr("Label") << tr("Address");
priv = new AddressTablePriv(); priv = new AddressTablePriv(wallet);
priv->refreshAddressTable(); priv->refreshAddressTable();
} }
@ -118,7 +118,7 @@ QVariant AddressTableModel::data(const QModelIndex &index, int role) const
case Address: case Address:
return rec->address; return rec->address;
case IsDefaultAddress: case IsDefaultAddress:
return rec->isDefaultAddress(); return priv->isDefaultAddress(rec);
} }
} }
else if (role == Qt::FontRole) else if (role == Qt::FontRole)
@ -128,7 +128,7 @@ QVariant AddressTableModel::data(const QModelIndex &index, int role) const
{ {
font = GUIUtil::bitcoinAddressFont(); font = GUIUtil::bitcoinAddressFont();
} }
if(rec->isDefaultAddress()) if(priv->isDefaultAddress(rec))
{ {
font.setBold(true); font.setBold(true);
} }
@ -137,14 +137,14 @@ QVariant AddressTableModel::data(const QModelIndex &index, int role) const
else if (role == Qt::ForegroundRole) else if (role == Qt::ForegroundRole)
{ {
// Show default address in alternative color // Show default address in alternative color
if(rec->isDefaultAddress()) if(priv->isDefaultAddress(rec))
{ {
return QColor(0,0,255); return QColor(0,0,255);
} }
} }
else if (role == Qt::ToolTipRole) else if (role == Qt::ToolTipRole)
{ {
if(rec->isDefaultAddress()) if(priv->isDefaultAddress(rec))
{ {
return tr("Default receiving address"); return tr("Default receiving address");
} }
@ -174,7 +174,7 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
switch(index.column()) switch(index.column())
{ {
case Label: case Label:
SetAddressBookName(rec->address.toStdString(), value.toString().toStdString()); wallet->SetAddressBookName(rec->address.toStdString(), value.toString().toStdString());
rec->label = value.toString(); rec->label = value.toString();
break; break;
case Address: case Address:
@ -182,9 +182,9 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
if(rec->type == AddressTableEntry::Sending) if(rec->type == AddressTableEntry::Sending)
{ {
// Remove old entry // Remove old entry
CWalletDB().EraseName(rec->address.toStdString()); wallet->EraseAddressBookName(rec->address.toStdString());
// Add new entry with new address // Add new entry with new address
SetAddressBookName(value.toString().toStdString(), rec->label.toStdString()); wallet->SetAddressBookName(value.toString().toStdString(), rec->label.toStdString());
rec->address = value.toString(); rec->address = value.toString();
} }
@ -245,9 +245,9 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
if(type == Send) if(type == Send)
{ {
// Check for duplicate // Check for duplicate
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(wallet->cs_mapAddressBook)
{ {
if(mapAddressBook.count(strAddress)) if(wallet->mapAddressBook.count(strAddress))
{ {
return QString(); return QString();
} }
@ -257,7 +257,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
{ {
// Generate a new address to associate with given label, optionally // Generate a new address to associate with given label, optionally
// set as default receiving address. // set as default receiving address.
strAddress = PubKeyToAddress(GetKeyFromKeyPool()); strAddress = PubKeyToAddress(wallet->GetKeyFromKeyPool());
if(setAsDefault) if(setAsDefault)
{ {
setDefaultAddress(QString::fromStdString(strAddress)); setDefaultAddress(QString::fromStdString(strAddress));
@ -268,7 +268,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
return QString(); return QString();
} }
// Add entry and update list // Add entry and update list
SetAddressBookName(strAddress, strLabel); wallet->SetAddressBookName(strAddress, strLabel);
updateList(); updateList();
return QString::fromStdString(strAddress); return QString::fromStdString(strAddress);
} }
@ -283,33 +283,19 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
// Also refuse to remove receiving addresses. // Also refuse to remove receiving addresses.
return false; return false;
} }
CWalletDB().EraseName(rec->address.toStdString()); wallet->EraseAddressBookName(rec->address.toStdString());
updateList(); updateList();
return true; return true;
} }
QString AddressTableModel::getDefaultAddress() const QString AddressTableModel::getDefaultAddress() const
{ {
std::vector<unsigned char> vchPubKey; return QString::fromStdString(wallet->GetDefaultAddress());
if (CWalletDB("r").ReadDefaultKey(vchPubKey))
{
return QString::fromStdString(PubKeyToAddress(vchPubKey));
}
else
{
return QString();
}
} }
void AddressTableModel::setDefaultAddress(const QString &defaultAddress) void AddressTableModel::setDefaultAddress(const QString &defaultAddress)
{ {
uint160 hash160; wallet->SetDefaultAddress(defaultAddress.toStdString());
std::string strAddress = defaultAddress.toStdString();
if (!AddressToHash160(strAddress, hash160))
return;
if (!mapPubKeys.count(hash160))
return;
CWalletDB().WriteDefaultKey(mapPubKeys[hash160]);
} }
void AddressTableModel::update() void AddressTableModel::update()

4
src/qt/addresstablemodel.h

@ -5,12 +5,13 @@
#include <QStringList> #include <QStringList>
class AddressTablePriv; class AddressTablePriv;
class CWallet;
class AddressTableModel : public QAbstractTableModel class AddressTableModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AddressTableModel(QObject *parent = 0); explicit AddressTableModel(CWallet *wallet, QObject *parent = 0);
~AddressTableModel(); ~AddressTableModel();
enum ColumnIndex { enum ColumnIndex {
@ -49,6 +50,7 @@ public:
void updateList(); void updateList();
private: private:
CWallet *wallet;
AddressTablePriv *priv; AddressTablePriv *priv;
QStringList columns; QStringList columns;

7
src/qt/bitcoin.cpp

@ -3,10 +3,9 @@
*/ */
#include "bitcoingui.h" #include "bitcoingui.h"
#include "clientmodel.h" #include "clientmodel.h"
#include "util.h"
#include "headers.h"
#include "init.h" #include "init.h"
#include "main.h"
#include "qtui.h"
#include <QApplication> #include <QApplication>
#include <QMessageBox> #include <QMessageBox>
@ -114,7 +113,7 @@ int main(int argc, char *argv[])
if(AppInit2(argc, argv)) if(AppInit2(argc, argv))
{ {
BitcoinGUI window; BitcoinGUI window;
ClientModel model; ClientModel model(pwalletMain);
guiref = &window; guiref = &window;
window.setModel(&model); window.setModel(&model);

2
src/qt/bitcoingui.cpp

@ -16,7 +16,7 @@
#include "transactiondescdialog.h" #include "transactiondescdialog.h"
#include "addresstablemodel.h" #include "addresstablemodel.h"
#include "main.h" #include "headers.h"
#include <QApplication> #include <QApplication>
#include <QMainWindow> #include <QMainWindow>

29
src/qt/clientmodel.cpp

@ -1,14 +1,15 @@
#include "clientmodel.h" #include "clientmodel.h"
#include "main.h"
#include "guiconstants.h" #include "guiconstants.h"
#include "optionsmodel.h" #include "optionsmodel.h"
#include "addresstablemodel.h" #include "addresstablemodel.h"
#include "transactiontablemodel.h" #include "transactiontablemodel.h"
#include "headers.h"
#include <QTimer> #include <QTimer>
ClientModel::ClientModel(QObject *parent) : ClientModel::ClientModel(CWallet *wallet, QObject *parent) :
QObject(parent), optionsModel(0), addressTableModel(0), QObject(parent), wallet(wallet), optionsModel(0), addressTableModel(0),
transactionTableModel(0) transactionTableModel(0)
{ {
// Until signal notifications is built into the bitcoin core, // Until signal notifications is built into the bitcoin core,
@ -17,14 +18,14 @@ ClientModel::ClientModel(QObject *parent) :
connect(timer, SIGNAL(timeout()), this, SLOT(update())); connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(MODEL_UPDATE_DELAY); timer->start(MODEL_UPDATE_DELAY);
optionsModel = new OptionsModel(this); optionsModel = new OptionsModel(wallet, this);
addressTableModel = new AddressTableModel(this); addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(this); transactionTableModel = new TransactionTableModel(wallet, this);
} }
qint64 ClientModel::getBalance() const qint64 ClientModel::getBalance() const
{ {
return GetBalance(); return wallet->GetBalance();
} }
int ClientModel::getNumConnections() const int ClientModel::getNumConnections() const
@ -40,9 +41,9 @@ int ClientModel::getNumBlocks() const
int ClientModel::getNumTransactions() const int ClientModel::getNumTransactions() const
{ {
int numTransactions = 0; int numTransactions = 0;
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(wallet->cs_mapWallet)
{ {
numTransactions = mapWallet.size(); numTransactions = wallet->mapWallet.size();
} }
return numTransactions; return numTransactions;
} }
@ -92,7 +93,7 @@ ClientModel::StatusCode ClientModel::sendCoins(const QString &payTo, qint64 payA
CScript scriptPubKey; CScript scriptPubKey;
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
std::string strError = SendMoney(scriptPubKey, payAmount, wtx, true); std::string strError = wallet->SendMoney(scriptPubKey, payAmount, wtx, true);
if (strError == "") if (strError == "")
{ {
// OK // OK
@ -110,9 +111,11 @@ ClientModel::StatusCode ClientModel::sendCoins(const QString &payTo, qint64 payA
// Add addresses that we've sent to to the address book // Add addresses that we've sent to to the address book
std::string strAddress = payTo.toStdString(); std::string strAddress = payTo.toStdString();
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(wallet->cs_mapAddressBook)
if (!mapAddressBook.count(strAddress)) {
SetAddressBookName(strAddress, addToAddressBookAs.toStdString()); if (!wallet->mapAddressBook.count(strAddress))
wallet->SetAddressBookName(strAddress, addToAddressBookAs.toStdString());
}
return OK; return OK;
} }

5
src/qt/clientmodel.h

@ -6,12 +6,13 @@
class OptionsModel; class OptionsModel;
class AddressTableModel; class AddressTableModel;
class TransactionTableModel; class TransactionTableModel;
class CWallet;
class ClientModel : public QObject class ClientModel : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ClientModel(QObject *parent = 0); explicit ClientModel(CWallet *wallet, QObject *parent = 0);
enum StatusCode enum StatusCode
{ {
@ -41,6 +42,8 @@ public:
/* Send coins */ /* Send coins */
StatusCode sendCoins(const QString &payTo, qint64 payAmount, const QString &addToAddressBookAs=QString()); StatusCode sendCoins(const QString &payTo, qint64 payAmount, const QString &addToAddressBookAs=QString());
private: private:
CWallet *wallet;
OptionsModel *optionsModel; OptionsModel *optionsModel;
AddressTableModel *addressTableModel; AddressTableModel *addressTableModel;
TransactionTableModel *transactionTableModel; TransactionTableModel *transactionTableModel;

11
src/qt/optionsmodel.cpp

@ -1,11 +1,12 @@
#include "optionsmodel.h" #include "optionsmodel.h"
#include "main.h"
#include "net.h" #include "headers.h"
#include <QDebug> #include <QDebug>
OptionsModel::OptionsModel(QObject *parent) : OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) :
QAbstractListModel(parent) QAbstractListModel(parent),
wallet(wallet)
{ {
} }
@ -48,7 +49,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
bool successful = true; /* set to false on parse error */ bool successful = true; /* set to false on parse error */
if(role == Qt::EditRole) if(role == Qt::EditRole)
{ {
CWalletDB walletdb; CWalletDB walletdb(wallet->strWalletFile);
switch(index.row()) switch(index.row())
{ {
case StartAtStartup: case StartAtStartup:

7
src/qt/optionsmodel.h

@ -3,6 +3,8 @@
#include <QAbstractListModel> #include <QAbstractListModel>
class CWallet;
/* Interface from QT to configuration data structure for bitcoin client. /* Interface from QT to configuration data structure for bitcoin client.
To QT, the options are presented as a list with the different options To QT, the options are presented as a list with the different options
laid out vertically. laid out vertically.
@ -13,7 +15,7 @@ class OptionsModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit OptionsModel(QObject *parent = 0); explicit OptionsModel(CWallet *wallet, QObject *parent = 0);
enum OptionID { enum OptionID {
StartAtStartup, StartAtStartup,
@ -35,6 +37,9 @@ public:
qint64 getTransactionFee(); qint64 getTransactionFee();
bool getMinimizeToTray(); bool getMinimizeToTray();
bool getMinimizeOnClose(); bool getMinimizeOnClose();
private:
// Wallet stores persistent options
CWallet *wallet;
signals: signals:
public slots: public slots:

54
src/qt/transactiondesc.cpp

@ -70,10 +70,10 @@ static string FormatTxStatus(const CWalletTx& wtx)
} }
} }
string TransactionDesc::toHTML(CWalletTx &wtx) string TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
{ {
string strHTML; string strHTML;
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(wallet->cs_mapAddressBook)
{ {
strHTML.reserve(4000); strHTML.reserve(4000);
strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
@ -122,19 +122,19 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
// Credit // Credit
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{ {
if (txout.IsMine()) if (wallet->IsMine(txout))
{ {
vector<unsigned char> vchPubKey; vector<unsigned char> vchPubKey;
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) if (ExtractPubKey(txout.scriptPubKey, wallet, vchPubKey))
{ {
string strAddress = PubKeyToAddress(vchPubKey); string strAddress = PubKeyToAddress(vchPubKey);
if (mapAddressBook.count(strAddress)) if (wallet->mapAddressBook.count(strAddress))
{ {
strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>"; strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
strHTML += _("<b>To:</b> "); strHTML += _("<b>To:</b> ");
strHTML += HtmlEscape(strAddress); strHTML += HtmlEscape(strAddress);
if (!mapAddressBook[strAddress].empty()) if (!wallet->mapAddressBook[strAddress].empty())
strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")"; strHTML += _(" (yours, label: ") + wallet->mapAddressBook[strAddress] + ")";
else else
strHTML += _(" (yours)"); strHTML += _(" (yours)");
strHTML += "<br>"; strHTML += "<br>";
@ -156,8 +156,8 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
// Online transaction // Online transaction
strAddress = wtx.mapValue["to"]; strAddress = wtx.mapValue["to"];
strHTML += _("<b>To:</b> "); strHTML += _("<b>To:</b> ");
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty()) if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].empty())
strHTML += mapAddressBook[strAddress] + " "; strHTML += wallet->mapAddressBook[strAddress] + " ";
strHTML += HtmlEscape(strAddress) + "<br>"; strHTML += HtmlEscape(strAddress) + "<br>";
} }
@ -172,7 +172,7 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
// //
int64 nUnmatured = 0; int64 nUnmatured = 0;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
nUnmatured += txout.GetCredit(); nUnmatured += wallet->GetCredit(txout);
strHTML += _("<b>Credit:</b> "); strHTML += _("<b>Credit:</b> ");
if (wtx.IsInMainChain()) if (wtx.IsInMainChain())
strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity()); strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
@ -191,11 +191,11 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
{ {
bool fAllFromMe = true; bool fAllFromMe = true;
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
fAllFromMe = fAllFromMe && txin.IsMine(); fAllFromMe = fAllFromMe && wallet->IsMine(txin);
bool fAllToMe = true; bool fAllToMe = true;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
fAllToMe = fAllToMe && txout.IsMine(); fAllToMe = fAllToMe && wallet->IsMine(txout);
if (fAllFromMe) if (fAllFromMe)
{ {
@ -204,7 +204,7 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
// //
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{ {
if (txout.IsMine()) if (wallet->IsMine(txout))
continue; continue;
if (wtx.mapValue["to"].empty()) if (wtx.mapValue["to"].empty())
@ -215,8 +215,8 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
{ {
string strAddress = Hash160ToAddress(hash160); string strAddress = Hash160ToAddress(hash160);
strHTML += _("<b>To:</b> "); strHTML += _("<b>To:</b> ");
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty()) if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].empty())
strHTML += mapAddressBook[strAddress] + " "; strHTML += wallet->mapAddressBook[strAddress] + " ";
strHTML += strAddress; strHTML += strAddress;
strHTML += "<br>"; strHTML += "<br>";
} }
@ -244,11 +244,11 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
// Mixed debit transaction // Mixed debit transaction
// //
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
if (txin.IsMine()) if (wallet->IsMine(txin))
strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>"; strHTML += _("<b>Debit:</b> ") + FormatMoney(-wallet->GetDebit(txin)) + "<br>";
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (txout.IsMine()) if (wallet->IsMine(txout))
strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>"; strHTML += _("<b>Credit:</b> ") + FormatMoney(wallet->GetCredit(txout)) + "<br>";
} }
} }
@ -274,30 +274,30 @@ string TransactionDesc::toHTML(CWalletTx &wtx)
{ {
strHTML += "<hr><br>debug print<br><br>"; strHTML += "<hr><br>debug print<br><br>";
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
if (txin.IsMine()) if(wallet->IsMine(txin))
strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>"; strHTML += "<b>Debit:</b> " + FormatMoney(-wallet->IsMine(txin)) + "<br>";
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (txout.IsMine()) if(wallet->IsMine(txout))
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>"; strHTML += "<b>Credit:</b> " + FormatMoney(wallet->IsMine(txout)) + "<br>";
strHTML += "<br><b>Transaction:</b><br>"; strHTML += "<br><b>Transaction:</b><br>";
strHTML += HtmlEscape(wtx.ToString(), true); strHTML += HtmlEscape(wtx.ToString(), true);
strHTML += "<br><b>Inputs:</b><br>"; strHTML += "<br><b>Inputs:</b><br>";
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(wallet->cs_mapWallet)
{ {
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{ {
COutPoint prevout = txin.prevout; COutPoint prevout = txin.prevout;
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash); map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(prevout.hash);
if (mi != mapWallet.end()) if (mi != wallet->mapWallet.end())
{ {
const CWalletTx& prev = (*mi).second; const CWalletTx& prev = (*mi).second;
if (prevout.n < prev.vout.size()) if (prevout.n < prev.vout.size())
{ {
strHTML += HtmlEscape(prev.ToString(), true); strHTML += HtmlEscape(prev.ToString(), true);
strHTML += " &nbsp;&nbsp; " + FormatTxStatus(prev) + ", "; strHTML += " &nbsp;&nbsp; " + FormatTxStatus(prev) + ", ";
strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>"; strHTML = strHTML + "IsMine=" + (wallet->IsMine(prev.vout[prevout.n]) ? "true" : "false") + "<br>";
} }
} }
} }

3
src/qt/transactiondesc.h

@ -3,13 +3,14 @@
#include <string> #include <string>
class CWallet;
class CWalletTx; class CWalletTx;
class TransactionDesc class TransactionDesc
{ {
public: public:
/* Provide human-readable extended HTML description of a transaction */ /* Provide human-readable extended HTML description of a transaction */
static std::string toHTML(CWalletTx &wtx); static std::string toHTML(CWallet *wallet, CWalletTx &wtx);
}; };
#endif // TRANSACTIONDESC_H #endif // TRANSACTIONDESC_H

21
src/qt/transactionrecord.cpp

@ -1,5 +1,6 @@
#include "transactionrecord.h" #include "transactionrecord.h"
#include "headers.h"
/* Return positive answer if transaction should be shown in list. /* Return positive answer if transaction should be shown in list.
*/ */
@ -29,7 +30,7 @@ bool TransactionRecord::showTransaction(const CWalletTx &wtx)
/* /*
* Decompose CWallet transaction to model transaction records. * Decompose CWallet transaction to model transaction records.
*/ */
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWalletTx &wtx) QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{ {
QList<TransactionRecord> parts; QList<TransactionRecord> parts;
int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime(); int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
@ -59,7 +60,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWalletTx
{ {
int64 nUnmatured = 0; int64 nUnmatured = 0;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
nUnmatured += txout.GetCredit(); nUnmatured += wallet->GetCredit(txout);
sub.credit = nUnmatured; sub.credit = nUnmatured;
} }
} }
@ -76,10 +77,10 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWalletTx
sub.type = TransactionRecord::RecvWithAddress; sub.type = TransactionRecord::RecvWithAddress;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{ {
if (txout.IsMine()) if(wallet->IsMine(txout))
{ {
std::vector<unsigned char> vchPubKey; std::vector<unsigned char> vchPubKey;
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) if (ExtractPubKey(txout.scriptPubKey, wallet, vchPubKey))
{ {
sub.address = PubKeyToAddress(vchPubKey); sub.address = PubKeyToAddress(vchPubKey);
} }
@ -93,11 +94,11 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWalletTx
{ {
bool fAllFromMe = true; bool fAllFromMe = true;
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
fAllFromMe = fAllFromMe && txin.IsMine(); fAllFromMe = fAllFromMe && wallet->IsMine(txin);
bool fAllToMe = true; bool fAllToMe = true;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
fAllToMe = fAllToMe && txout.IsMine(); fAllToMe = fAllToMe && wallet->IsMine(txout);
if (fAllFromMe && fAllToMe) if (fAllFromMe && fAllToMe)
{ {
@ -120,13 +121,13 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWalletTx
TransactionRecord sub(hash, nTime); TransactionRecord sub(hash, nTime);
sub.idx = parts.size(); sub.idx = parts.size();
if (txout.IsMine()) if(wallet->IsMine(txout))
{ {
// Ignore parts sent to self, as this is usually the change // Ignore parts sent to self, as this is usually the change
// from a transaction sent back to our own address. // from a transaction sent back to our own address.
continue; continue;
} }
else if (!mapValue["to"].empty()) else if(!mapValue["to"].empty())
{ {
// Sent to IP // Sent to IP
sub.type = TransactionRecord::SendToIP; sub.type = TransactionRecord::SendToIP;
@ -160,9 +161,9 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWalletTx
// //
bool fAllMine = true; bool fAllMine = true;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
fAllMine = fAllMine && txout.IsMine(); fAllMine = fAllMine && wallet->IsMine(txout);
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
fAllMine = fAllMine && txin.IsMine(); fAllMine = fAllMine && wallet->IsMine(txin);
parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
} }

4
src/qt/transactionrecord.h

@ -5,6 +5,8 @@
#include <QList> #include <QList>
class CWallet;
class TransactionStatus class TransactionStatus
{ {
public: public:
@ -84,7 +86,7 @@ public:
/* Decompose CWallet transaction to model transaction records. /* Decompose CWallet transaction to model transaction records.
*/ */
static bool showTransaction(const CWalletTx &wtx); static bool showTransaction(const CWalletTx &wtx);
static QList<TransactionRecord> decomposeTransaction(const CWalletTx &wtx); static QList<TransactionRecord> decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx);
/* Fixed */ /* Fixed */
uint256 hash; uint256 hash;

58
src/qt/transactiontablemodel.cpp

@ -2,9 +2,10 @@
#include "guiutil.h" #include "guiutil.h"
#include "transactionrecord.h" #include "transactionrecord.h"
#include "guiconstants.h" #include "guiconstants.h"
#include "main.h"
#include "transactiondesc.h" #include "transactiondesc.h"
#include "headers.h"
#include <QLocale> #include <QLocale>
#include <QDebug> #include <QDebug>
#include <QList> #include <QList>
@ -37,11 +38,12 @@ struct TxLessThan
// Private implementation // Private implementation
struct TransactionTablePriv struct TransactionTablePriv
{ {
TransactionTablePriv(TransactionTableModel *parent): TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent):
wallet(wallet),
parent(parent) parent(parent)
{ {
} }
CWallet *wallet;
TransactionTableModel *parent; TransactionTableModel *parent;
/* Local cache of wallet. /* Local cache of wallet.
@ -58,11 +60,11 @@ struct TransactionTablePriv
qDebug() << "refreshWallet"; qDebug() << "refreshWallet";
#endif #endif
cachedWallet.clear(); cachedWallet.clear();
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(wallet->cs_mapWallet)
{ {
for(std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
{ {
cachedWallet.append(TransactionRecord::decomposeTransaction(it->second)); cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second));
} }
} }
} }
@ -84,14 +86,14 @@ struct TransactionTablePriv
QList<uint256> updated_sorted = updated; QList<uint256> updated_sorted = updated;
qSort(updated_sorted); qSort(updated_sorted);
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(wallet->cs_mapWallet)
{ {
for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx) for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx)
{ {
const uint256 &hash = updated_sorted.at(update_idx); const uint256 &hash = updated_sorted.at(update_idx);
/* Find transaction in wallet */ /* Find transaction in wallet */
std::map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
bool inWallet = mi != mapWallet.end(); bool inWallet = mi != wallet->mapWallet.end();
/* Find bounds of this transaction in model */ /* Find bounds of this transaction in model */
QList<TransactionRecord>::iterator lower = qLowerBound( QList<TransactionRecord>::iterator lower = qLowerBound(
cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
@ -100,6 +102,7 @@ struct TransactionTablePriv
int lowerIndex = (lower - cachedWallet.begin()); int lowerIndex = (lower - cachedWallet.begin());
int upperIndex = (upper - cachedWallet.begin()); int upperIndex = (upper - cachedWallet.begin());
// Determine if transaction is in model already
bool inModel = false; bool inModel = false;
if(lower != upper) if(lower != upper)
{ {
@ -115,7 +118,7 @@ struct TransactionTablePriv
{ {
// Added -- insert at the right position // Added -- insert at the right position
QList<TransactionRecord> toInsert = QList<TransactionRecord> toInsert =
TransactionRecord::decomposeTransaction(mi->second); TransactionRecord::decomposeTransaction(wallet, mi->second);
if(!toInsert.isEmpty()) /* only if something to insert */ if(!toInsert.isEmpty()) /* only if something to insert */
{ {
parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1); parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
@ -159,11 +162,11 @@ struct TransactionTablePriv
// simply re-use the cached status. // simply re-use the cached status.
if(rec->statusUpdateNeeded()) if(rec->statusUpdateNeeded())
{ {
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(wallet->cs_mapWallet)
{ {
std::map<uint256, CWalletTx>::iterator mi = mapWallet.find(rec->hash); std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != mapWallet.end()) if(mi != wallet->mapWallet.end())
{ {
rec->updateStatus(mi->second); rec->updateStatus(mi->second);
} }
@ -179,12 +182,12 @@ struct TransactionTablePriv
QString describe(TransactionRecord *rec) QString describe(TransactionRecord *rec)
{ {
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(wallet->cs_mapWallet)
{ {
std::map<uint256, CWalletTx>::iterator mi = mapWallet.find(rec->hash); std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != mapWallet.end()) if(mi != wallet->mapWallet.end())
{ {
return QString::fromStdString(TransactionDesc::toHTML(mi->second)); return QString::fromStdString(TransactionDesc::toHTML(wallet, mi->second));
} }
} }
return QString(""); return QString("");
@ -202,9 +205,10 @@ static int column_alignments[] = {
Qt::AlignLeft|Qt::AlignVCenter Qt::AlignLeft|Qt::AlignVCenter
}; };
TransactionTableModel::TransactionTableModel(QObject *parent): TransactionTableModel::TransactionTableModel(CWallet* wallet, QObject *parent):
QAbstractTableModel(parent), QAbstractTableModel(parent),
priv(new TransactionTablePriv(this)) wallet(wallet),
priv(new TransactionTablePriv(wallet, this))
{ {
columns << tr("Status") << tr("Date") << tr("Description") << tr("Debit") << tr("Credit"); columns << tr("Status") << tr("Date") << tr("Description") << tr("Debit") << tr("Credit");
@ -225,15 +229,15 @@ void TransactionTableModel::update()
QList<uint256> updated; QList<uint256> updated;
// Check if there are changes to wallet map // Check if there are changes to wallet map
TRY_CRITICAL_BLOCK(cs_mapWallet) TRY_CRITICAL_BLOCK(wallet->cs_mapWallet)
{ {
if(!vWalletUpdated.empty()) if(!wallet->vWalletUpdated.empty())
{ {
BOOST_FOREACH(uint256 hash, vWalletUpdated) BOOST_FOREACH(uint256 hash, wallet->vWalletUpdated)
{ {
updated.append(hash); updated.append(hash);
} }
vWalletUpdated.clear(); wallet->vWalletUpdated.clear();
} }
} }
@ -302,13 +306,13 @@ QVariant TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const
address[0:12]... (label) address[0:12]... (label)
otherwise just return address otherwise just return address
*/ */
std::string lookupAddress(const std::string &address) std::string TransactionTableModel::lookupAddress(const std::string &address) const
{ {
std::string description; std::string description;
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(wallet->cs_mapAddressBook)
{ {
std::map<std::string, std::string>::iterator mi = mapAddressBook.find(address); std::map<std::string, std::string>::iterator mi = wallet->mapAddressBook.find(address);
if (mi != mapAddressBook.end() && !(*mi).second.empty()) if (mi != wallet->mapAddressBook.end() && !(*mi).second.empty())
{ {
std::string label = (*mi).second; std::string label = (*mi).second;
description += address.substr(0,12) + "... "; description += address.substr(0,12) + "... ";

5
src/qt/transactiontablemodel.h

@ -4,6 +4,7 @@
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QStringList> #include <QStringList>
class CWallet;
class TransactionTablePriv; class TransactionTablePriv;
class TransactionRecord; class TransactionRecord;
@ -11,7 +12,7 @@ class TransactionTableModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TransactionTableModel(QObject *parent = 0); explicit TransactionTableModel(CWallet* wallet, QObject *parent = 0);
~TransactionTableModel(); ~TransactionTableModel();
enum { enum {
@ -39,9 +40,11 @@ public:
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
private: private:
CWallet* wallet;
QStringList columns; QStringList columns;
TransactionTablePriv *priv; TransactionTablePriv *priv;
std::string lookupAddress(const std::string &address) const;
QVariant formatTxStatus(const TransactionRecord *wtx) const; QVariant formatTxStatus(const TransactionRecord *wtx) const;
QVariant formatTxDate(const TransactionRecord *wtx) const; QVariant formatTxDate(const TransactionRecord *wtx) const;
QVariant formatTxDescription(const TransactionRecord *wtx) const; QVariant formatTxDescription(const TransactionRecord *wtx) const;

1
src/qtui.h

@ -6,6 +6,7 @@
#include <string> #include <string>
#include <boost/function/function0.hpp> #include <boost/function/function0.hpp>
#include "wallet.h"
typedef void wxWindow; typedef void wxWindow;
#define wxYES 0x00000002 #define wxYES 0x00000002

149
src/rpc.cpp

@ -14,6 +14,7 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#ifdef USE_SSL #ifdef USE_SSL
#include <boost/asio/ssl.hpp> #include <boost/asio/ssl.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream; typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
#endif #endif
@ -264,14 +265,14 @@ Value setgenerate(const Array& params, bool fHelp)
{ {
int nGenProcLimit = params[1].get_int(); int nGenProcLimit = params[1].get_int();
fLimitProcessors = (nGenProcLimit != -1); fLimitProcessors = (nGenProcLimit != -1);
CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors); WriteSetting("fLimitProcessors", fLimitProcessors);
if (nGenProcLimit != -1) if (nGenProcLimit != -1)
CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit); WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
if (nGenProcLimit == 0) if (nGenProcLimit == 0)
fGenerate = false; fGenerate = false;
} }
GenerateBitcoins(fGenerate); GenerateBitcoins(fGenerate, pwalletMain);
return Value::null; return Value::null;
} }
@ -298,7 +299,7 @@ Value getinfo(const Array& params, bool fHelp)
Object obj; Object obj;
obj.push_back(Pair("version", (int)VERSION)); 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("blocks", (int)nBestHeight));
obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
@ -307,7 +308,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("hashespersec", gethashespersec(params, false))); obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
obj.push_back(Pair("testnet", fTestNet)); 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("paytxfee", ValueFromAmount(nTransactionFee)));
obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj; return obj;
@ -329,9 +330,9 @@ Value getnewaddress(const Array& params, bool fHelp)
strAccount = AccountFromValue(params[0]); strAccount = AccountFromValue(params[0]);
// Generate a new key that is added to wallet // 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; return strAddress;
} }
@ -341,7 +342,7 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
{ {
string strAddress; string strAddress;
CWalletDB walletdb; CWalletDB walletdb(pwalletMain->strWalletFile);
walletdb.TxnBegin(); walletdb.TxnBegin();
CAccount account; CAccount account;
@ -352,8 +353,8 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
{ {
CScript scriptPubKey; CScript scriptPubKey;
scriptPubKey.SetBitcoinAddress(account.vchPubKey); scriptPubKey.SetBitcoinAddress(account.vchPubKey);
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
it != mapWallet.end() && !account.vchPubKey.empty(); it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
++it) ++it)
{ {
const CWalletTx& wtx = (*it).second; const CWalletTx& wtx = (*it).second;
@ -366,9 +367,9 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
// Generate a new key // Generate a new key
if (account.vchPubKey.empty() || bForceNew) if (account.vchPubKey.empty() || bForceNew)
{ {
account.vchPubKey = GetKeyFromKeyPool(); account.vchPubKey = pwalletMain->GetKeyFromKeyPool();
string strAddress = PubKeyToAddress(account.vchPubKey); string strAddress = PubKeyToAddress(account.vchPubKey);
SetAddressBookName(strAddress, strAccount); pwalletMain->SetAddressBookName(strAddress, strAccount);
walletdb.WriteAccount(strAccount, account); walletdb.WriteAccount(strAccount, account);
} }
@ -391,7 +392,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
Value ret; Value ret;
CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{ {
ret = GetAccountAddress(strAccount); ret = GetAccountAddress(strAccount);
} }
@ -421,18 +422,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: // Detect when changing the account of an address that is the 'unused current key' of another account:
CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(cs_mapAddressBook) 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)) if (strAddress == GetAccountAddress(strOldAccount))
GetAccountAddress(strOldAccount, true); GetAccountAddress(strOldAccount, true);
} }
} }
SetAddressBookName(strAddress, strAccount); pwalletMain->SetAddressBookName(strAddress, strAccount);
return Value::null; return Value::null;
} }
@ -447,10 +448,10 @@ Value getaccount(const Array& params, bool fHelp)
string strAddress = params[0].get_str(); string strAddress = params[0].get_str();
string strAccount; string strAccount;
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{ {
map<string, string>::iterator mi = mapAddressBook.find(strAddress); map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
if (mi != mapAddressBook.end() && !(*mi).second.empty()) if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
strAccount = (*mi).second; strAccount = (*mi).second;
} }
return strAccount; return strAccount;
@ -468,9 +469,9 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
// Find all addresses that have the given account // Find all addresses that have the given account
Array ret; Array ret;
CRITICAL_BLOCK(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& strAddress = item.first;
const string& strName = item.second; const string& strName = item.second;
@ -523,7 +524,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_main)
{ {
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
if (strError != "") if (strError != "")
throw JSONRPCError(-4, strError); throw JSONRPCError(-4, strError);
} }
@ -544,7 +545,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
CScript scriptPubKey; CScript scriptPubKey;
if (!scriptPubKey.SetBitcoinAddress(strAddress)) if (!scriptPubKey.SetBitcoinAddress(strAddress))
throw JSONRPCError(-5, "Invalid bitcoin address"); throw JSONRPCError(-5, "Invalid bitcoin address");
if (!IsMine(scriptPubKey)) if (!IsMine(*pwalletMain,scriptPubKey))
return (double)0.0; return (double)0.0;
// Minimum confirmations // Minimum confirmations
@ -554,9 +555,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
// Tally // Tally
int64 nAmount = 0; 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; const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal()) if (wtx.IsCoinBase() || !wtx.IsFinal())
@ -575,9 +576,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey) 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& strAddress = item.first;
const string& strName = item.second; const string& strName = item.second;
@ -586,7 +587,7 @@ void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
// We're only counting our own valid bitcoin addresses and not ip addresses // We're only counting our own valid bitcoin addresses and not ip addresses
CScript scriptPubKey; CScript scriptPubKey;
if (scriptPubKey.SetBitcoinAddress(strAddress)) if (scriptPubKey.SetBitcoinAddress(strAddress))
if (IsMine(scriptPubKey)) if (IsMine(*pwalletMain,scriptPubKey))
setPubKey.insert(scriptPubKey); setPubKey.insert(scriptPubKey);
} }
} }
@ -613,9 +614,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
// Tally // Tally
int64 nAmount = 0; 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; const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal()) if (wtx.IsCoinBase() || !wtx.IsFinal())
@ -635,10 +636,10 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth) int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
{ {
int64 nBalance = 0; int64 nBalance = 0;
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{ {
// Tally wallet transactions // 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; const CWalletTx& wtx = (*it).second;
if (!wtx.IsFinal()) if (!wtx.IsFinal())
@ -661,7 +662,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
int64 GetAccountBalance(const string& strAccount, int nMinDepth) int64 GetAccountBalance(const string& strAccount, int nMinDepth)
{ {
CWalletDB walletdb; CWalletDB walletdb(pwalletMain->strWalletFile);
return GetAccountBalance(walletdb, strAccount, nMinDepth); return GetAccountBalance(walletdb, strAccount, nMinDepth);
} }
@ -675,7 +676,7 @@ Value getbalance(const Array& params, bool fHelp)
"If [account] is specified, returns the balance in the account."); "If [account] is specified, returns the balance in the account.");
if (params.size() == 0) if (params.size() == 0)
return ValueFromAmount(GetBalance()); return ValueFromAmount(pwalletMain->GetBalance());
int nMinDepth = 1; int nMinDepth = 1;
if (params.size() > 1) if (params.size() > 1)
@ -686,7 +687,7 @@ Value getbalance(const Array& params, bool fHelp)
// (GetBalance() sums up all unspent TxOuts) // (GetBalance() sums up all unspent TxOuts)
// getbalance and getbalance '*' should always return the same number. // getbalance and getbalance '*' should always return the same number.
int64 nBalance = 0; 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; const CWalletTx& wtx = (*it).second;
if (!wtx.IsFinal()) if (!wtx.IsFinal())
@ -734,9 +735,9 @@ Value movecmd(const Array& params, bool fHelp)
if (params.size() > 4) if (params.size() > 4)
strComment = params[4].get_str(); strComment = params[4].get_str();
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{ {
CWalletDB walletdb; CWalletDB walletdb(pwalletMain->strWalletFile);
walletdb.TxnBegin(); walletdb.TxnBegin();
int64 nNow = GetAdjustedTime(); int64 nNow = GetAdjustedTime();
@ -787,7 +788,7 @@ Value sendfrom(const Array& params, bool fHelp)
wtx.mapValue["to"] = params[5].get_str(); wtx.mapValue["to"] = params[5].get_str();
CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{ {
// Check funds // Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth); int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@ -795,7 +796,7 @@ Value sendfrom(const Array& params, bool fHelp)
throw JSONRPCError(-6, "Account has insufficient funds"); throw JSONRPCError(-6, "Account has insufficient funds");
// Send // Send
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
if (strError != "") if (strError != "")
throw JSONRPCError(-4, strError); throw JSONRPCError(-4, strError);
} }
@ -844,7 +845,7 @@ Value sendmany(const Array& params, bool fHelp)
} }
CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{ {
// Check funds // Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth); int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@ -852,16 +853,16 @@ Value sendmany(const Array& params, bool fHelp)
throw JSONRPCError(-6, "Account has insufficient funds"); throw JSONRPCError(-6, "Account has insufficient funds");
// Send // Send
CReserveKey keyChange; CReserveKey keyChange(pwalletMain);
int64 nFeeRequired = 0; int64 nFeeRequired = 0;
bool fCreated = CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
if (!fCreated) if (!fCreated)
{ {
if (totalAmount + nFeeRequired > GetBalance()) if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
throw JSONRPCError(-6, "Insufficient funds"); throw JSONRPCError(-6, "Insufficient funds");
throw JSONRPCError(-4, "Transaction creation failed"); throw JSONRPCError(-4, "Transaction creation failed");
} }
if (!CommitTransaction(wtx, keyChange)) if (!pwalletMain->CommitTransaction(wtx, keyChange))
throw JSONRPCError(-4, "Transaction commit failed"); throw JSONRPCError(-4, "Transaction commit failed");
} }
@ -894,9 +895,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
// Tally // Tally
map<uint160, tallyitem> mapTally; 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; const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal()) if (wtx.IsCoinBase() || !wtx.IsFinal())
@ -923,9 +924,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
// Reply // Reply
Array ret; Array ret;
map<string, tallyitem> mapAccountTally; 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& strAddress = item.first;
const string& strAccount = item.second; const string& strAccount = item.second;
@ -1061,13 +1062,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Received // Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{ {
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived) BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
{ {
string account; string account;
if (mapAddressBook.count(r.first)) if (pwalletMain->mapAddressBook.count(r.first))
account = mapAddressBook[r.first]; account = pwalletMain->mapAddressBook[r.first];
if (fAllAccounts || (account == strAccount)) if (fAllAccounts || (account == strAccount))
{ {
Object entry; Object entry;
@ -1119,16 +1120,16 @@ Value listtransactions(const Array& params, bool fHelp)
nFrom = params[2].get_int(); nFrom = params[2].get_int();
Array ret; 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: // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
typedef pair<CWalletTx*, CAccountingEntry*> TxPair; typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
typedef multimap<int64, TxPair > TxItems; typedef multimap<int64, TxPair > TxItems;
TxItems txByTime; 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); CWalletTx* wtx = &((*it).second);
txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0))); txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
@ -1180,16 +1181,16 @@ Value listaccounts(const Array& params, bool fHelp)
nMinDepth = params[0].get_int(); nMinDepth = params[0].get_int();
map<string, int64> mapAccountBalances; map<string, int64> mapAccountBalances;
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{ {
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, mapAddressBook) { BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
uint160 hash160; uint160 hash160;
if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
mapAccountBalances[entry.second] = 0; 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; const CWalletTx& wtx = (*it).second;
int64 nGeneratedImmature, nGeneratedMature, nFee; int64 nGeneratedImmature, nGeneratedMature, nFee;
@ -1204,8 +1205,8 @@ Value listaccounts(const Array& params, bool fHelp)
{ {
mapAccountBalances[""] += nGeneratedMature; mapAccountBalances[""] += nGeneratedMature;
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived) BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
if (mapAddressBook.count(r.first)) if (pwalletMain->mapAddressBook.count(r.first))
mapAccountBalances[mapAddressBook[r.first]] += r.second; mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
else else
mapAccountBalances[""] += r.second; mapAccountBalances[""] += r.second;
} }
@ -1213,7 +1214,7 @@ Value listaccounts(const Array& params, bool fHelp)
} }
list<CAccountingEntry> acentries; list<CAccountingEntry> acentries;
CWalletDB().ListAccountCreditDebit("*", acentries); CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
BOOST_FOREACH(const CAccountingEntry& entry, acentries) BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit; mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
@ -1235,11 +1236,11 @@ Value gettransaction(const Array& params, bool fHelp)
hash.SetHex(params[0].get_str()); hash.SetHex(params[0].get_str());
Object entry; Object entry;
CRITICAL_BLOCK(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"); 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 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit(); int64 nDebit = wtx.GetDebit();
@ -1250,10 +1251,10 @@ Value gettransaction(const Array& params, bool fHelp)
if (wtx.IsFromMe()) if (wtx.IsFromMe())
entry.push_back(Pair("fee", ValueFromAmount(nFee))); entry.push_back(Pair("fee", ValueFromAmount(nFee)));
WalletTxToJSON(mapWallet[hash], entry); WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
Array details; Array details;
ListTransactions(mapWallet[hash], "*", 0, false, details); ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
entry.push_back(Pair("details", details)); entry.push_back(Pair("details", details));
} }
@ -1269,7 +1270,7 @@ Value backupwallet(const Array& params, bool fHelp)
"Safely copies wallet.dat to destination, which can be a directory or a path with filename."); "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
string strDest = params[0].get_str(); string strDest = params[0].get_str();
BackupWallet(strDest); BackupWallet(*pwalletMain, strDest);
return Value::null; return Value::null;
} }
@ -1295,10 +1296,10 @@ Value validateaddress(const Array& params, bool fHelp)
string currentAddress = Hash160ToAddress(hash160); string currentAddress = Hash160ToAddress(hash160);
ret.push_back(Pair("address", currentAddress)); ret.push_back(Pair("address", currentAddress));
ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0))); ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
CRITICAL_BLOCK(cs_mapAddressBook) CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{ {
if (mapAddressBook.count(currentAddress)) if (pwalletMain->mapAddressBook.count(currentAddress))
ret.push_back(Pair("account", mapAddressBook[currentAddress])); ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress]));
} }
} }
return ret; return ret;
@ -1325,7 +1326,7 @@ Value getwork(const Array& params, bool fHelp)
static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock; static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
static vector<CBlock*> vNewBlock; static vector<CBlock*> vNewBlock;
static CReserveKey reservekey; static CReserveKey reservekey(pwalletMain);
if (params.size() == 0) if (params.size() == 0)
{ {
@ -1406,7 +1407,7 @@ Value getwork(const Array& params, bool fHelp)
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce); pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
pblock->hashMerkleRoot = pblock->BuildMerkleTree(); pblock->hashMerkleRoot = pblock->BuildMerkleTree();
return CheckWork(pblock, reservekey); return CheckWork(pblock, *pwalletMain, reservekey);
} }
} }

33
src/script.cpp

@ -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(); scriptSigRet.clear();
@ -1030,7 +1030,7 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
return false; return false;
// Compile solution // Compile solution
CRITICAL_BLOCK(cs_mapKeys) CRITICAL_BLOCK(keystore.cs_mapKeys)
{ {
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution) BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{ {
@ -1038,12 +1038,13 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
{ {
// Sign // Sign
const valtype& vchPubKey = item.second; const valtype& vchPubKey = item.second;
if (!mapKeys.count(vchPubKey)) CPrivKey privkey;
if (!keystore.GetPrivKey(vchPubKey, privkey))
return false; return false;
if (hash != 0) if (hash != 0)
{ {
vector<unsigned char> vchSig; vector<unsigned char> vchSig;
if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig)) if (!CKey::Sign(privkey, hash, vchSig))
return false; return false;
vchSig.push_back((unsigned char)nHashType); vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig; scriptSigRet << vchSig;
@ -1056,12 +1057,13 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
if (mi == mapPubKeys.end()) if (mi == mapPubKeys.end())
return false; return false;
const vector<unsigned char>& vchPubKey = (*mi).second; const vector<unsigned char>& vchPubKey = (*mi).second;
if (!mapKeys.count(vchPubKey)) CPrivKey privkey;
if (!keystore.GetPrivKey(vchPubKey, privkey))
return false; return false;
if (hash != 0) if (hash != 0)
{ {
vector<unsigned char> vchSig; vector<unsigned char> vchSig;
if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig)) if (!CKey::Sign(privkey, hash, vchSig))
return false; return false;
vchSig.push_back((unsigned char)nHashType); vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig << vchPubKey; scriptSigRet << vchSig << vchPubKey;
@ -1085,14 +1087,14 @@ bool IsStandard(const CScript& scriptPubKey)
} }
bool IsMine(const CScript& scriptPubKey) bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
{ {
CScript scriptSig; 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(); vchPubKeyRet.clear();
@ -1100,7 +1102,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
if (!Solver(scriptPubKey, vSolution)) if (!Solver(scriptPubKey, vSolution))
return false; return false;
CRITICAL_BLOCK(cs_mapKeys) CRITICAL_BLOCK(cs_mapPubKeys)
{ {
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution) BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{ {
@ -1116,7 +1118,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
continue; continue;
vchPubKey = (*mi).second; vchPubKey = (*mi).second;
} }
if (!fMineOnly || mapKeys.count(vchPubKey)) if (keystore == NULL || keystore->HaveKey(vchPubKey))
{ {
vchPubKeyRet = vchPubKey; vchPubKeyRet = vchPubKey;
return true; return true;
@ -1160,7 +1162,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()); assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn]; CTxIn& txin = txTo.vin[nIn];
@ -1171,7 +1173,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int
// The checksig op will also drop the signatures from its hash. // The checksig op will also drop the signatures from its hash.
uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType); 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; return false;
txin.scriptSig = scriptPrereq + txin.scriptSig; txin.scriptSig = scriptPrereq + txin.scriptSig;
@ -1199,10 +1201,5 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType)) if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType))
return false; 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; return true;
} }

8
src/script.h

@ -5,6 +5,7 @@
#define H_BITCOIN_SCRIPT #define H_BITCOIN_SCRIPT
#include "base58.h" #include "base58.h"
#include "keystore.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -707,12 +708,11 @@ public:
uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
bool IsStandard(const CScript& scriptPubKey); bool IsStandard(const CScript& scriptPubKey);
bool IsMine(const CScript& scriptPubKey); bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, std::vector<unsigned char>& vchPubKeyRet); bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* pkeystore, std::vector<unsigned char>& vchPubKeyRet);
bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret); 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); bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
#endif #endif

2
src/util.cpp

@ -5,7 +5,7 @@
#include "strlcpy.h" #include "strlcpy.h"
#include <boost/program_options/detail/config_file.hpp> #include <boost/program_options/detail/config_file.hpp>
#include <boost/program_options/parsers.hpp> #include <boost/program_options/parsers.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>

4
src/util.h

@ -139,14 +139,12 @@ inline int myclosesocket(SOCKET& hSocket)
return ret; return ret;
} }
#define closesocket(s) myclosesocket(s) #define closesocket(s) myclosesocket(s)
#if 0 #if !defined(QT_GUI) && !defined(GUI)
#ifndef GUI
inline const char* _(const char* psz) inline const char* _(const char* psz)
{ {
return psz; return psz;
} }
#endif #endif
#endif

1176
src/wallet.cpp

File diff suppressed because it is too large Load Diff

611
src/wallet.h

@ -0,0 +1,611 @@
// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_H
#define BITCOIN_WALLET_H
#include "bignum.h"
#include "key.h"
#include "script.h"
class CWalletTx;
class CReserveKey;
class CWalletDB;
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;
public:
bool fFileBacked;
std::string strWalletFile;
std::set<int64> setKeyPool;
CCriticalSection cs_setKeyPool;
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;
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");
return (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);
bool EraseAddressBookName(const std::string& strAddress);
std::string GetDefaultAddress();
bool SetDefaultAddress(const std::string& strAddress);
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();
};
//
// A transaction with a bunch of additional info that only the owner cares
// about. It includes any unrecorded transactions needed to link it back
// to the block chain.
//
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;
unsigned int fTimeReceivedIsTxTime;
unsigned int nTimeReceived; // time received by this node
char fFromMe;
std::string strFromAccount;
std::vector<char> vfSpent;
// memory only
mutable char fDebitCached;
mutable char fCreditCached;
mutable char fAvailableCreditCached;
mutable char fChangeCached;
mutable int64 nDebitCached;
mutable int64 nCreditCached;
mutable int64 nAvailableCreditCached;
mutable int64 nChangeCached;
// memory only UI hints
mutable unsigned int nTimeDisplayed;
mutable int nLinesDisplayed;
mutable char fConfirmedDisplayed;
CWalletTx()
{
Init(NULL);
}
CWalletTx(const CWallet* pwalletIn)
{
Init(pwalletIn);
}
CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
{
Init(pwalletIn);
}
CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
{
Init(pwalletIn);
}
void Init(const CWallet* pwalletIn)
{
pwallet = pwalletIn;
vtxPrev.clear();
mapValue.clear();
vOrderForm.clear();
fTimeReceivedIsTxTime = false;
nTimeReceived = 0;
fFromMe = false;
strFromAccount.clear();
vfSpent.clear();
fDebitCached = false;
fCreditCached = false;
fAvailableCreditCached = false;
fChangeCached = false;
nDebitCached = 0;
nCreditCached = 0;
nAvailableCreditCached = 0;
nChangeCached = 0;
nTimeDisplayed = 0;
nLinesDisplayed = 0;
fConfirmedDisplayed = false;
}
IMPLEMENT_SERIALIZE
(
CWalletTx* pthis = const_cast<CWalletTx*>(this);
if (fRead)
pthis->Init(NULL);
char fSpent = false;
if (!fRead)
{
pthis->mapValue["fromaccount"] = pthis->strFromAccount;
std::string str;
BOOST_FOREACH(char f, vfSpent)
{
str += (f ? '1' : '0');
if (f)
fSpent = true;
}
pthis->mapValue["spent"] = str;
}
nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
READWRITE(vtxPrev);
READWRITE(mapValue);
READWRITE(vOrderForm);
READWRITE(fTimeReceivedIsTxTime);
READWRITE(nTimeReceived);
READWRITE(fFromMe);
READWRITE(fSpent);
if (fRead)
{
pthis->strFromAccount = pthis->mapValue["fromaccount"];
if (mapValue.count("spent"))
BOOST_FOREACH(char c, pthis->mapValue["spent"])
pthis->vfSpent.push_back(c != '0');
else
pthis->vfSpent.assign(vout.size(), fSpent);
}
pthis->mapValue.erase("fromaccount");
pthis->mapValue.erase("version");
pthis->mapValue.erase("spent");
)
// marks certain txout's as spent
// returns true if any update took place
bool UpdateSpent(const std::vector<char>& vfNewSpent)
{
bool fReturn = false;
for (int i=0; i < vfNewSpent.size(); i++)
{
if (i == vfSpent.size())
break;
if (vfNewSpent[i] && !vfSpent[i])
{
vfSpent[i] = true;
fReturn = true;
fAvailableCreditCached = false;
}
}
return fReturn;
}
void MarkDirty()
{
fCreditCached = false;
fAvailableCreditCached = false;
fDebitCached = false;
fChangeCached = false;
}
void MarkSpent(unsigned int nOut)
{
if (nOut >= vout.size())
throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
vfSpent.resize(vout.size());
if (!vfSpent[nOut])
{
vfSpent[nOut] = true;
fAvailableCreditCached = false;
}
}
bool IsSpent(unsigned int nOut) const
{
if (nOut >= vout.size())
throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
if (nOut >= vfSpent.size())
return false;
return (!!vfSpent[nOut]);
}
int64 GetDebit() const
{
if (vin.empty())
return 0;
if (fDebitCached)
return nDebitCached;
nDebitCached = pwallet->GetDebit(*this);
fDebitCached = true;
return nDebitCached;
}
int64 GetCredit(bool fUseCache=true) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
// GetBalance can assume transactions in mapWallet won't change
if (fUseCache && fCreditCached)
return nCreditCached;
nCreditCached = pwallet->GetCredit(*this);
fCreditCached = true;
return nCreditCached;
}
int64 GetAvailableCredit(bool fUseCache=true) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
if (fUseCache && fAvailableCreditCached)
return nAvailableCreditCached;
int64 nCredit = 0;
for (int i = 0; i < vout.size(); i++)
{
if (!IsSpent(i))
{
const CTxOut &txout = vout[i];
nCredit += pwallet->GetCredit(txout);
if (!MoneyRange(nCredit))
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
}
}
nAvailableCreditCached = nCredit;
fAvailableCreditCached = true;
return nCredit;
}
int64 GetChange() const
{
if (fChangeCached)
return nChangeCached;
nChangeCached = pwallet->GetChange(*this);
fChangeCached = true;
return nChangeCached;
}
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,
int64& nSent, int64& nFee) const;
bool IsFromMe() const
{
return (GetDebit() > 0);
}
bool IsConfirmed() const
{
// Quick answer in most cases
if (!IsFinal())
return false;
if (GetDepthInMainChain() >= 1)
return true;
if (!IsFromMe()) // using wtx's cached debit
return false;
// If no confirmations but it's from us, we can still
// consider it confirmed if all dependencies are confirmed
std::map<uint256, const CMerkleTx*> mapPrev;
std::vector<const CMerkleTx*> vWorkQueue;
vWorkQueue.reserve(vtxPrev.size()+1);
vWorkQueue.push_back(this);
for (int i = 0; i < vWorkQueue.size(); i++)
{
const CMerkleTx* ptx = vWorkQueue[i];
if (!ptx->IsFinal())
return false;
if (ptx->GetDepthInMainChain() >= 1)
continue;
if (!pwallet->IsFromMe(*ptx))
return false;
if (mapPrev.empty())
BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
mapPrev[tx.GetHash()] = &tx;
BOOST_FOREACH(const CTxIn& txin, ptx->vin)
{
if (!mapPrev.count(txin.prevout.hash))
return false;
vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
}
}
return true;
}
bool WriteToDisk();
int64 GetTxTime() const;
int GetRequestCount() const;
void AddSupportingTransactions(CTxDB& txdb);
bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
bool AcceptWalletTransaction();
void RelayWalletTransaction(CTxDB& txdb);
void RelayWalletTransaction();
};
//
// Private key that includes an expiration date in case it never gets used.
//
class CWalletKey
{
public:
CPrivKey vchPrivKey;
int64 nTimeCreated;
int64 nTimeExpires;
std::string strComment;
//// todo: add something to note what created it (user, getnewaddress, change)
//// maybe should have a map<string, string> property map
CWalletKey(int64 nExpires=0)
{
nTimeCreated = (nExpires ? GetTime() : 0);
nTimeExpires = nExpires;
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPrivKey);
READWRITE(nTimeCreated);
READWRITE(nTimeExpires);
READWRITE(strComment);
)
};
//
// Account information.
// Stored in wallet with key "acc"+string account name
//
class CAccount
{
public:
std::vector<unsigned char> vchPubKey;
CAccount()
{
SetNull();
}
void SetNull()
{
vchPubKey.clear();
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPubKey);
)
};
//
// Internal transfers.
// Database key is acentry<account><counter>
//
class CAccountingEntry
{
public:
std::string strAccount;
int64 nCreditDebit;
int64 nTime;
std::string strOtherAccount;
std::string strComment;
CAccountingEntry()
{
SetNull();
}
void SetNull()
{
nCreditDebit = 0;
nTime = 0;
strAccount.clear();
strOtherAccount.clear();
strComment.clear();
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
// Note: strAccount is serialized as part of the key, not here.
READWRITE(nCreditDebit);
READWRITE(nTime);
READWRITE(strOtherAccount);
READWRITE(strComment);
)
};
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
#endif
Loading…
Cancel
Save