* A new class CKeyStore manages private keys, and script.cpp depends on access to CKeyStore. * A new class CWallet extends CKeyStore, and contains all former wallet-specific globals; CWallet depends on script.cpp, not the other way around. * Wallet-specific functions in CTransaction/CTxIn/CTxOut (GetDebit, GetCredit, GetChange, IsMine, IsFromMe), are moved to CWallet, taking their former 'this' argument as an explicit parameter * CWalletTx objects know which CWallet they belong to, for convenience, so they have their own direct (and caching) GetDebit/... functions. * Some code was moved from CWalletDB to CWallet, such as handling of reserve keys. * Main.cpp keeps a set of all 'registered' wallets, which should be informed about updates to the block chain, and does not have any notion about any 'main' wallet. Function in main.cpp that require a wallet (such as GenerateCoins), take an explicit CWallet* argument. * The actual CWallet instance used by the application is defined in init.cpp as "CWallet* pwalletMain". rpc.cpp and ui.cpp use this variable. * Functions in main.cpp and db.cpp that are not used by other modules are marked static. * The code for handling the 'submitorder' message is removed, as it not really compatible with the idea that a node is independent from the wallet(s) connected to it, and obsolete anyway.tags/v0.15.1
@@ -10,8 +10,6 @@ | |||
using namespace std; | |||
using namespace boost; | |||
void ThreadFlushWalletDB(void* parg); | |||
unsigned int nWalletDBUpdated; | |||
uint64 nAccountingEntryNumber = 0; | |||
@@ -150,7 +148,7 @@ void CDB::Close() | |||
--mapFileUseCount[strFile]; | |||
} | |||
void CloseDb(const string& strFile) | |||
void static CloseDb(const string& strFile) | |||
{ | |||
CRITICAL_BLOCK(cs_db) | |||
{ | |||
@@ -359,7 +357,7 @@ bool CTxDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork) | |||
return Write(string("bnBestInvalidWork"), bnBestInvalidWork); | |||
} | |||
CBlockIndex* InsertBlockIndex(uint256 hash) | |||
CBlockIndex static * InsertBlockIndex(uint256 hash) | |||
{ | |||
if (hash == 0) | |||
return NULL; | |||
@@ -584,6 +582,20 @@ bool LoadAddresses() | |||
// CWalletDB | |||
// | |||
bool CWalletDB::WriteName(const string& strAddress, const string& strName) | |||
{ | |||
nWalletDBUpdated++; | |||
return Write(make_pair(string("name"), strAddress), strName); | |||
} | |||
bool CWalletDB::EraseName(const string& strAddress) | |||
{ | |||
// This should only be used for sending addresses, never for receiving addresses, | |||
// receiving addresses must always have an address book entry if they're not change return. | |||
nWalletDBUpdated++; | |||
return Erase(make_pair(string("name"), strAddress)); | |||
} | |||
bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account) | |||
{ | |||
account.SetNull(); | |||
@@ -657,9 +669,9 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin | |||
} | |||
bool CWalletDB::LoadWallet() | |||
bool CWalletDB::LoadWallet(CWallet* pwallet) | |||
{ | |||
vchDefaultKey.clear(); | |||
pwallet->vchDefaultKey.clear(); | |||
int nFileVersion = 0; | |||
vector<uint256> vWalletUpgrade; | |||
@@ -671,8 +683,8 @@ bool CWalletDB::LoadWallet() | |||
#endif | |||
//// todo: shouldn't we catch exceptions and try to recover and continue? | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(cs_mapKeys) | |||
CRITICAL_BLOCK(pwallet->cs_mapWallet) | |||
CRITICAL_BLOCK(pwallet->cs_mapKeys) | |||
{ | |||
// Get cursor | |||
Dbc* pcursor = GetCursor(); | |||
@@ -699,14 +711,15 @@ bool CWalletDB::LoadWallet() | |||
{ | |||
string strAddress; | |||
ssKey >> strAddress; | |||
ssValue >> mapAddressBook[strAddress]; | |||
ssValue >> pwallet->mapAddressBook[strAddress]; | |||
} | |||
else if (strType == "tx") | |||
{ | |||
uint256 hash; | |||
ssKey >> hash; | |||
CWalletTx& wtx = mapWallet[hash]; | |||
CWalletTx& wtx = pwallet->mapWallet[hash]; | |||
ssValue >> wtx; | |||
wtx.pwallet = pwallet; | |||
if (wtx.GetHash() != hash) | |||
printf("Error in wallet.dat, hash mismatch\n"); | |||
@@ -757,18 +770,18 @@ bool CWalletDB::LoadWallet() | |||
else | |||
ssValue >> wkey; | |||
mapKeys[vchPubKey] = wkey.vchPrivKey; | |||
pwallet->mapKeys[vchPubKey] = wkey.vchPrivKey; | |||
mapPubKeys[Hash160(vchPubKey)] = vchPubKey; | |||
} | |||
else if (strType == "defaultkey") | |||
{ | |||
ssValue >> vchDefaultKey; | |||
ssValue >> pwallet->vchDefaultKey; | |||
} | |||
else if (strType == "pool") | |||
{ | |||
int64 nIndex; | |||
ssKey >> nIndex; | |||
setKeyPool.insert(nIndex); | |||
pwallet->setKeyPool.insert(nIndex); | |||
} | |||
else if (strType == "version") | |||
{ | |||
@@ -800,7 +813,7 @@ bool CWalletDB::LoadWallet() | |||
} | |||
BOOST_FOREACH(uint256 hash, vWalletUpgrade) | |||
WriteTx(hash, mapWallet[hash]); | |||
WriteTx(hash, pwallet->mapWallet[hash]); | |||
printf("nFileVersion = %d\n", nFileVersion); | |||
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins); | |||
@@ -830,6 +843,7 @@ bool CWalletDB::LoadWallet() | |||
void ThreadFlushWalletDB(void* parg) | |||
{ | |||
const string& strFile = ((const string*)parg)[0]; | |||
static bool fOneThread; | |||
if (fOneThread) | |||
return; | |||
@@ -865,7 +879,6 @@ void ThreadFlushWalletDB(void* parg) | |||
if (nRefCount == 0 && !fShutdown) | |||
{ | |||
string strFile = "wallet.dat"; | |||
map<string, int>::iterator mi = mapFileUseCount.find(strFile); | |||
if (mi != mapFileUseCount.end()) | |||
{ | |||
@@ -888,26 +901,27 @@ void ThreadFlushWalletDB(void* parg) | |||
} | |||
} | |||
void BackupWallet(const string& strDest) | |||
bool BackupWallet(const CWallet& wallet, const string& strDest) | |||
{ | |||
if (!wallet.fFileBacked) | |||
return false; | |||
while (!fShutdown) | |||
{ | |||
CRITICAL_BLOCK(cs_db) | |||
{ | |||
const string strFile = "wallet.dat"; | |||
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0) | |||
if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0) | |||
{ | |||
// Flush log data to the dat file | |||
CloseDb(strFile); | |||
CloseDb(wallet.strWalletFile); | |||
dbenv.txn_checkpoint(0, 0, 0); | |||
dbenv.lsn_reset(strFile.c_str(), 0); | |||
mapFileUseCount.erase(strFile); | |||
dbenv.lsn_reset(wallet.strWalletFile.c_str(), 0); | |||
mapFileUseCount.erase(wallet.strWalletFile); | |||
// Copy wallet.dat | |||
filesystem::path pathSrc(GetDataDir() + "/" + strFile); | |||
filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile); | |||
filesystem::path pathDest(strDest); | |||
if (filesystem::is_directory(pathDest)) | |||
pathDest = pathDest / strFile; | |||
pathDest = pathDest / wallet.strWalletFile; | |||
#if BOOST_VERSION >= 104000 | |||
filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); | |||
#else | |||
@@ -915,11 +929,10 @@ void BackupWallet(const string& strDest) | |||
#endif | |||
printf("copied wallet.dat to %s\n", pathDest.string().c_str()); | |||
return; | |||
return true; | |||
} | |||
} | |||
Sleep(100); | |||
} | |||
return false; | |||
} | |||
@@ -12,33 +12,25 @@ | |||
#include <db_cxx.h> | |||
class CTransaction; | |||
class CTxIndex; | |||
class CDiskBlockIndex; | |||
class CDiskTxPos; | |||
class COutPoint; | |||
class CUser; | |||
class CReview; | |||
class CAddress; | |||
class CWalletTx; | |||
class CWallet; | |||
class CAccount; | |||
class CAccountingEntry; | |||
class CBlockLocator; | |||
extern std::vector<unsigned char> vchDefaultKey; | |||
extern bool fClient; | |||
extern int nBestHeight; | |||
extern unsigned int nWalletDBUpdated; | |||
extern DbEnv dbenv; | |||
extern void DBFlush(bool fShutdown); | |||
extern std::vector<unsigned char> GetKeyFromKeyPool(); | |||
extern int64 GetOldestKeyPoolTime(); | |||
extern void ThreadFlushWalletDB(void* parg); | |||
void ThreadFlushWalletDB(void* parg); | |||
bool BackupWallet(const CWallet& wallet, const std::string& strDest); | |||
@@ -321,9 +313,6 @@ bool LoadAddresses(); | |||
class CKeyPool | |||
{ | |||
public: | |||
@@ -356,7 +345,7 @@ public: | |||
class CWalletDB : public CDB | |||
{ | |||
public: | |||
CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode) | |||
CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode) | |||
{ | |||
} | |||
private: | |||
@@ -369,23 +358,9 @@ public: | |||
return Read(std::make_pair(std::string("name"), strAddress), strName); | |||
} | |||
bool WriteName(const std::string& strAddress, const std::string& strName) | |||
{ | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
mapAddressBook[strAddress] = strName; | |||
nWalletDBUpdated++; | |||
return Write(std::make_pair(std::string("name"), strAddress), strName); | |||
} | |||
bool WriteName(const std::string& strAddress, const std::string& strName); | |||
bool EraseName(const std::string& strAddress) | |||
{ | |||
// This should only be used for sending addresses, never for receiving addresses, | |||
// receiving addresses must always have an address book entry if they're not change return. | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
mapAddressBook.erase(strAddress); | |||
nWalletDBUpdated++; | |||
return Erase(std::make_pair(std::string("name"), strAddress)); | |||
} | |||
bool EraseName(const std::string& strAddress); | |||
bool ReadTx(uint256 hash, CWalletTx& wtx) | |||
{ | |||
@@ -435,11 +410,27 @@ public: | |||
bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey) | |||
{ | |||
vchDefaultKey = vchPubKey; | |||
nWalletDBUpdated++; | |||
return Write(std::string("defaultkey"), vchPubKey); | |||
} | |||
bool ReadPool(int64 nPool, CKeyPool& keypool) | |||
{ | |||
return Read(std::make_pair(std::string("pool"), nPool), keypool); | |||
} | |||
bool WritePool(int64 nPool, const CKeyPool& keypool) | |||
{ | |||
nWalletDBUpdated++; | |||
return Write(std::make_pair(std::string("pool"), nPool), keypool); | |||
} | |||
bool ErasePool(int64 nPool) | |||
{ | |||
nWalletDBUpdated++; | |||
return Erase(std::make_pair(std::string("pool"), nPool)); | |||
} | |||
template<typename T> | |||
bool ReadSetting(const std::string& strKey, T& value) | |||
{ | |||
@@ -459,44 +450,7 @@ public: | |||
int64 GetAccountCreditDebit(const std::string& strAccount); | |||
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries); | |||
bool LoadWallet(); | |||
protected: | |||
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool); | |||
void KeepKey(int64 nIndex); | |||
static void ReturnKey(int64 nIndex); | |||
friend class CReserveKey; | |||
friend std::vector<unsigned char> GetKeyFromKeyPool(); | |||
friend int64 GetOldestKeyPoolTime(); | |||
}; | |||
bool LoadWallet(bool& fFirstRunRet); | |||
void BackupWallet(const std::string& strDest); | |||
inline bool SetAddressBookName(const std::string& strAddress, const std::string& strName) | |||
{ | |||
return CWalletDB().WriteName(strAddress, strName); | |||
} | |||
class CReserveKey | |||
{ | |||
protected: | |||
int64 nIndex; | |||
std::vector<unsigned char> vchPubKey; | |||
public: | |||
CReserveKey() | |||
{ | |||
nIndex = -1; | |||
} | |||
~CReserveKey() | |||
{ | |||
if (!fShutdown) | |||
ReturnKey(); | |||
} | |||
std::vector<unsigned char> GetReservedKey(); | |||
void KeepKey(); | |||
void ReturnKey(); | |||
bool LoadWallet(CWallet* pwallet); | |||
}; | |||
#endif |
@@ -13,6 +13,8 @@ | |||
using namespace std; | |||
using namespace boost; | |||
CWallet* pwalletMain; | |||
////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Shutdown | |||
@@ -45,6 +47,8 @@ void Shutdown(void* parg) | |||
StopNode(); | |||
DBFlush(true); | |||
boost::filesystem::remove(GetPidFile()); | |||
UnregisterWallet(pwalletMain); | |||
delete pwalletMain; | |||
CreateThread(ExitTimeout, NULL); | |||
Sleep(50); | |||
printf("Bitcoin exiting\n\n"); | |||
@@ -372,16 +376,19 @@ bool AppInit2(int argc, char* argv[]) | |||
printf("Loading wallet...\n"); | |||
nStart = GetTimeMillis(); | |||
bool fFirstRun; | |||
if (!LoadWallet(fFirstRun)) | |||
pwalletMain = new CWallet("wallet.dat"); | |||
if (!pwalletMain->LoadWallet(fFirstRun)) | |||
strErrors += _("Error loading wallet.dat \n"); | |||
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart); | |||
RegisterWallet(pwalletMain); | |||
CBlockIndex *pindexRescan = pindexBest; | |||
if (GetBoolArg("-rescan")) | |||
pindexRescan = pindexGenesisBlock; | |||
else | |||
{ | |||
CWalletDB walletdb; | |||
CWalletDB walletdb("wallet.dat"); | |||
CBlockLocator locator; | |||
if (walletdb.ReadBestBlock(locator)) | |||
pindexRescan = locator.GetBlockIndex(); | |||
@@ -390,7 +397,7 @@ bool AppInit2(int argc, char* argv[]) | |||
{ | |||
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); | |||
nStart = GetTimeMillis(); | |||
ScanForWalletTransactions(pindexRescan, true); | |||
pwalletMain->ScanForWalletTransactions(pindexRescan, true); | |||
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); | |||
} | |||
@@ -399,10 +406,11 @@ bool AppInit2(int argc, char* argv[]) | |||
//// debug print | |||
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size()); | |||
printf("nBestHeight = %d\n", nBestHeight); | |||
printf("mapKeys.size() = %d\n", mapKeys.size()); | |||
printf("mapKeys.size() = %d\n", pwalletMain->mapKeys.size()); | |||
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size()); | |||
printf("mapPubKeys.size() = %d\n", mapPubKeys.size()); | |||
printf("mapWallet.size() = %d\n", mapWallet.size()); | |||
printf("mapAddressBook.size() = %d\n", mapAddressBook.size()); | |||
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size()); | |||
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size()); | |||
if (!strErrors.empty()) | |||
{ | |||
@@ -411,7 +419,7 @@ bool AppInit2(int argc, char* argv[]) | |||
} | |||
// Add wallet transactions that aren't already in a block to mapTransactions | |||
ReacceptWalletTransactions(); | |||
pwalletMain->ReacceptWalletTransactions(); | |||
// | |||
// Parameters |
@@ -4,6 +4,8 @@ | |||
#ifndef BITCOIN_INIT_H | |||
#define BITCOIN_INIT_H | |||
extern CWallet* pwalletMain; | |||
void Shutdown(void* parg); | |||
bool AppInit(int argc, char* argv[]); | |||
bool AppInit2(int argc, char* argv[]); |
@@ -12,7 +12,7 @@ | |||
// mapKeys | |||
// | |||
std::vector<unsigned char> GenerateNewKey() | |||
std::vector<unsigned char> CKeyStore::GenerateNewKey() | |||
{ | |||
RandAddSeedPerfmon(); | |||
CKey key; | |||
@@ -22,12 +22,12 @@ std::vector<unsigned char> GenerateNewKey() | |||
return key.GetPubKey(); | |||
} | |||
bool AddKey(const CKey& key) | |||
bool CKeyStore::AddKey(const CKey& key) | |||
{ | |||
CRITICAL_BLOCK(cs_mapKeys) | |||
{ | |||
mapKeys[key.GetPubKey()] = key.GetPrivKey(); | |||
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey(); | |||
} | |||
return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey()); | |||
} | |||
@@ -4,7 +4,23 @@ | |||
#ifndef BITCOIN_KEYSTORE_H | |||
#define BITCOIN_KEYSTORE_H | |||
bool AddKey(const CKey& key); | |||
std::vector<unsigned char> GenerateNewKey(); | |||
class CKeyStore | |||
{ | |||
public: | |||
std::map<std::vector<unsigned char>, CPrivKey> mapKeys; | |||
mutable CCriticalSection cs_mapKeys; | |||
virtual bool AddKey(const CKey& key); | |||
bool HaveKey(const std::vector<unsigned char> &vchPubKey) const | |||
{ | |||
return (mapKeys.count(vchPubKey) > 0); | |||
} | |||
CPrivKey GetPrivKey(const std::vector<unsigned char> &vchPubKey) const | |||
{ | |||
std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey); | |||
if (mi != mapKeys.end()) | |||
return (*mi).second; | |||
} | |||
std::vector<unsigned char> GenerateNewKey(); | |||
}; | |||
#endif |
@@ -15,8 +15,14 @@ using namespace boost; | |||
// Global state | |||
// | |||
CCriticalSection cs_setpwalletRegistered; | |||
set<CWallet*> setpwalletRegistered; | |||
CCriticalSection cs_main; | |||
CCriticalSection cs_mapPubKeys; | |||
map<uint160, vector<unsigned char> > mapPubKeys; | |||
map<uint256, CTransaction> mapTransactions; | |||
CCriticalSection cs_mapTransactions; | |||
unsigned int nTransactionsUpdated = 0; | |||
@@ -39,25 +45,6 @@ multimap<uint256, CBlock*> mapOrphanBlocksByPrev; | |||
map<uint256, CDataStream*> mapOrphanTransactions; | |||
multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev; | |||
map<uint256, CWalletTx> mapWallet; | |||
vector<uint256> vWalletUpdated; | |||
CCriticalSection cs_mapWallet; | |||
map<vector<unsigned char>, CPrivKey> mapKeys; | |||
map<uint160, vector<unsigned char> > mapPubKeys; | |||
CCriticalSection cs_mapKeys; | |||
CKey keyUser; | |||
map<uint256, int> mapRequestCount; | |||
CCriticalSection cs_mapRequestCount; | |||
map<string, string> mapAddressBook; | |||
CCriticalSection cs_mapAddressBook; | |||
set<int64> setKeyPool; | |||
CCriticalSection cs_setKeyPool; | |||
vector<unsigned char> vchDefaultKey; | |||
double dHashesPerSec; | |||
int64 nHPSTimerStart; | |||
@@ -82,12 +69,97 @@ int fUseUPnP = false; | |||
////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// dispatching functions | |||
// | |||
void RegisterWallet(CWallet* pwalletIn) | |||
{ | |||
CRITICAL_BLOCK(cs_setpwalletRegistered) | |||
{ | |||
setpwalletRegistered.insert(pwalletIn); | |||
} | |||
} | |||
void UnregisterWallet(CWallet* pwalletIn) | |||
{ | |||
CRITICAL_BLOCK(cs_setpwalletRegistered) | |||
{ | |||
setpwalletRegistered.erase(pwalletIn); | |||
} | |||
} | |||
bool static IsFromMe(CTransaction& tx) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
if (pwallet->IsFromMe(tx)) | |||
return true; | |||
return false; | |||
} | |||
bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
if (pwallet->GetTransaction(hashTx,wtx)) | |||
return true; | |||
return false; | |||
} | |||
void static EraseFromWallets(uint256 hash) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
pwallet->EraseFromWallet(hash); | |||
} | |||
void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); | |||
} | |||
void static SetBestChain(const CBlockLocator& loc) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
pwallet->SetBestChain(loc); | |||
} | |||
void static UpdatedTransaction(const uint256& hashTx) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
pwallet->UpdatedTransaction(hashTx); | |||
} | |||
void static PrintWallets(const CBlock& block) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
pwallet->PrintWallet(block); | |||
} | |||
void static Inventory(const uint256& hash) | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
pwallet->Inventory(hash); | |||
} | |||
void static ResendWalletTransactions() | |||
{ | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
pwallet->ResendWalletTransactions(); | |||
} | |||
////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// mapOrphanTransactions | |||
// | |||
void AddOrphanTx(const CDataStream& vMsg) | |||
void static AddOrphanTx(const CDataStream& vMsg) | |||
{ | |||
CTransaction tx; | |||
CDataStream(vMsg) >> tx; | |||
@@ -99,7 +171,7 @@ void AddOrphanTx(const CDataStream& vMsg) | |||
mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg)); | |||
} | |||
void EraseOrphanTx(uint256 hash) | |||
void static EraseOrphanTx(uint256 hash) | |||
{ | |||
if (!mapOrphanTransactions.count(hash)) | |||
return; | |||
@@ -357,7 +429,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi | |||
nLastTime = nNow; | |||
// -limitfreerelay unit is thousand-bytes-per-minute | |||
// At default rate it would take over a month to fill 1GB | |||
if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe()) | |||
if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this)) | |||
return error("AcceptToMemoryPool() : free transaction rejected by rate limiter"); | |||
if (fDebug) | |||
printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); | |||
@@ -380,7 +452,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi | |||
///// are we sure this is ok when loading transactions or restoring block txes | |||
// If updated, erase old tx from wallet | |||
if (ptxOld) | |||
EraseFromWallet(ptxOld->GetHash()); | |||
EraseFromWallets(ptxOld->GetHash()); | |||
printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str()); | |||
return true; | |||
@@ -551,8 +623,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions) | |||
return true; | |||
} | |||
uint256 GetOrphanRoot(const CBlock* pblock) | |||
uint256 static GetOrphanRoot(const CBlock* pblock) | |||
{ | |||
// Work back to the first block in the orphan chain | |||
while (mapOrphanBlocks.count(pblock->hashPrevBlock)) | |||
@@ -560,7 +631,7 @@ uint256 GetOrphanRoot(const CBlock* pblock) | |||
return pblock->GetHash(); | |||
} | |||
int64 GetBlockValue(int nHeight, int64 nFees) | |||
int64 static GetBlockValue(int nHeight, int64 nFees) | |||
{ | |||
int64 nSubsidy = 50 * COIN; | |||
@@ -570,7 +641,7 @@ int64 GetBlockValue(int nHeight, int64 nFees) | |||
return nSubsidy + nFees; | |||
} | |||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast) | |||
unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast) | |||
{ | |||
const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks | |||
const int64 nTargetSpacing = 10 * 60; | |||
@@ -647,7 +718,7 @@ bool IsInitialBlockDownload() | |||
pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60); | |||
} | |||
void InvalidChainFound(CBlockIndex* pindexNew) | |||
void static InvalidChainFound(CBlockIndex* pindexNew) | |||
{ | |||
if (pindexNew->bnChainWork > bnBestInvalidWork) | |||
{ | |||
@@ -923,12 +994,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) | |||
// Watch for transactions paying to me | |||
BOOST_FOREACH(CTransaction& tx, vtx) | |||
AddToWalletIfInvolvingMe(tx, this, true); | |||
SyncWithWallets(tx, this, true); | |||
return true; | |||
} | |||
bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) | |||
bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) | |||
{ | |||
printf("REORGANIZE\n"); | |||
@@ -1066,10 +1137,8 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) | |||
// Update best block in wallet (so we can detect restored wallets) | |||
if (!IsInitialBlockDownload()) | |||
{ | |||
CWalletDB walletdb; | |||
const CBlockLocator locator(pindexNew); | |||
if (!walletdb.WriteBestBlock(locator)) | |||
return error("SetBestChain() : WriteWalletBest failed"); | |||
::SetBestChain(locator); | |||
} | |||
// New best block | |||
@@ -1123,8 +1192,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) | |||
{ | |||
// Notify UI to display prev block's coinbase if it was ours | |||
static uint256 hashPrevBestCoinBase; | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
vWalletUpdated.push_back(hashPrevBestCoinBase); | |||
UpdatedTransaction(hashPrevBestCoinBase); | |||
hashPrevBestCoinBase = vtx[0].GetHash(); | |||
} | |||
@@ -1233,7 +1301,7 @@ bool CBlock::AcceptBlock() | |||
return true; | |||
} | |||
bool ProcessBlock(CNode* pfrom, CBlock* pblock) | |||
bool static ProcessBlock(CNode* pfrom, CBlock* pblock) | |||
{ | |||
// Check for duplicate | |||
uint256 hash = pblock->GetHash(); | |||
@@ -1295,7 +1363,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) | |||
template<typename Stream> | |||
bool ScanMessageStart(Stream& s) | |||
bool static ScanMessageStart(Stream& s) | |||
{ | |||
// Scan ahead to the next pchMessageStart, which should normally be immediately | |||
// at the file pointer. Leaves file pointer at end of pchMessageStart. | |||
@@ -1510,7 +1578,7 @@ void PrintBlockTree() | |||
for (int i = 0; i < nCol; i++) | |||
printf("| "); | |||
printf("|\n"); | |||
} | |||
} | |||
nPrevCol = nCol; | |||
// print columns | |||
@@ -1528,16 +1596,7 @@ void PrintBlockTree() | |||
DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(), | |||
block.vtx.size()); | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
{ | |||
if (mapWallet.count(block.vtx[0].GetHash())) | |||
{ | |||
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; | |||
printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); | |||
} | |||
} | |||
printf("\n"); | |||
PrintWallets(block); | |||
// put the main timechain first | |||
vector<CBlockIndex*>& vNext = mapNext[pindex]; | |||
@@ -1677,7 +1736,7 @@ bool CAlert::ProcessAlert() | |||
// | |||
bool AlreadyHave(CTxDB& txdb, const CInv& inv) | |||
bool static AlreadyHave(CTxDB& txdb, const CInv& inv) | |||
{ | |||
switch (inv.type) | |||
{ | |||
@@ -1697,7 +1756,7 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv) | |||
char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 }; | |||
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
{ | |||
static map<unsigned int, vector<unsigned char> > mapReuseKey; | |||
RandAddSeedPerfmon(); | |||
@@ -1894,12 +1953,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); | |||
// Track requests for our stuff | |||
CRITICAL_BLOCK(cs_mapRequestCount) | |||
{ | |||
map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash); | |||
if (mi != mapRequestCount.end()) | |||
(*mi).second++; | |||
} | |||
Inventory(inv.hash); | |||
} | |||
} | |||
@@ -1952,12 +2006,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
} | |||
// Track requests for our stuff | |||
CRITICAL_BLOCK(cs_mapRequestCount) | |||
{ | |||
map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash); | |||
if (mi != mapRequestCount.end()) | |||
(*mi).second++; | |||
} | |||
Inventory(inv.hash); | |||
} | |||
} | |||
@@ -2045,7 +2094,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
bool fMissingInputs = false; | |||
if (tx.AcceptToMemoryPool(true, &fMissingInputs)) | |||
{ | |||
AddToWalletIfInvolvingMe(tx, NULL, true); | |||
SyncWithWallets(tx, NULL, true); | |||
RelayMessage(inv, vMsg); | |||
mapAlreadyAskedFor.erase(inv); | |||
vWorkQueue.push_back(inv.hash); | |||
@@ -2066,7 +2115,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
if (tx.AcceptToMemoryPool(true)) | |||
{ | |||
printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str()); | |||
AddToWalletIfInvolvingMe(tx, NULL, true); | |||
SyncWithWallets(tx, NULL, true); | |||
RelayMessage(inv, vMsg); | |||
mapAlreadyAskedFor.erase(inv); | |||
vWorkQueue.push_back(inv.hash); | |||
@@ -2143,7 +2192,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
// Keep giving the same key to the same ip until they use it | |||
if (!mapReuseKey.count(pfrom->addr.ip)) | |||
mapReuseKey[pfrom->addr.ip] = GetKeyFromKeyPool(); | |||
mapReuseKey[pfrom->addr.ip] = pwalletMain->GetKeyFromKeyPool(); | |||
// Send back approval of order and pubkey to use | |||
CScript scriptPubKey; | |||
@@ -2152,37 +2201,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
} | |||
else if (strCommand == "submitorder") | |||
{ | |||
uint256 hashReply; | |||
vRecv >> hashReply; | |||
if (!GetBoolArg("-allowreceivebyip")) | |||
{ | |||
pfrom->PushMessage("reply", hashReply, (int)2); | |||
return true; | |||
} | |||
CWalletTx wtxNew; | |||
vRecv >> wtxNew; | |||
wtxNew.fFromMe = false; | |||
// Broadcast | |||
if (!wtxNew.AcceptWalletTransaction()) | |||
{ | |||
pfrom->PushMessage("reply", hashReply, (int)1); | |||
return error("submitorder AcceptWalletTransaction() failed, returning error 1"); | |||
} | |||
wtxNew.fTimeReceivedIsTxTime = true; | |||
AddToWallet(wtxNew); | |||
wtxNew.RelayWalletTransaction(); | |||
mapReuseKey.erase(pfrom->addr.ip); | |||
// Send back confirmation | |||
pfrom->PushMessage("reply", hashReply, (int)0); | |||
} | |||
else if (strCommand == "reply") | |||
{ | |||
uint256 hashReply; | |||
@@ -2239,7 +2257,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
return true; | |||
} | |||
bool ProcessMessages(CNode* pfrom) | |||
{ | |||
CDataStream& vRecv = pfrom->vRecv; | |||
@@ -2359,8 +2376,6 @@ bool ProcessMessages(CNode* pfrom) | |||
} | |||
bool SendMessages(CNode* pto, bool fSendTrickle) | |||
{ | |||
CRITICAL_BLOCK(cs_main) | |||
@@ -2483,16 +2498,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle) | |||
// always trickle our own transactions | |||
if (!fTrickleWait) | |||
{ | |||
TRY_CRITICAL_BLOCK(cs_mapWallet) | |||
{ | |||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(inv.hash); | |||
if (mi != mapWallet.end()) | |||
{ | |||
CWalletTx& wtx = (*mi).second; | |||
if (wtx.fFromMe) | |||
fTrickleWait = true; | |||
} | |||
} | |||
CWalletTx wtx; | |||
if (GetTransaction(inv.hash, wtx)) | |||
if (wtx.fFromMe) | |||
fTrickleWait = true; | |||
} | |||
if (fTrickleWait) | |||
@@ -2565,7 +2574,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) | |||
// BitcoinMiner | |||
// | |||
int FormatHashBlocks(void* pbuffer, unsigned int len) | |||
int static FormatHashBlocks(void* pbuffer, unsigned int len) | |||
{ | |||
unsigned char* pdata = (unsigned char*)pbuffer; | |||
unsigned int blocks = 1 + ((len + 8) / 64); | |||
@@ -2598,7 +2607,7 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit) | |||
// between calls, but periodically or if nNonce is 0xffff0000 or above, | |||
// the block is rebuilt and nNonce starts over at zero. | |||
// | |||
unsigned int ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone) | |||
unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone) | |||
{ | |||
unsigned int& nNonce = *(unsigned int*)(pdata + 12); | |||
for (;;) | |||
@@ -2855,7 +2864,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash | |||
} | |||
bool CheckWork(CBlock* pblock, CReserveKey& reservekey) | |||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) | |||
{ | |||
uint256 hash = pblock->GetHash(); | |||
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); | |||
@@ -2880,8 +2889,8 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey) | |||
reservekey.KeepKey(); | |||
// Track how many getdata requests this block gets | |||
CRITICAL_BLOCK(cs_mapRequestCount) | |||
mapRequestCount[pblock->GetHash()] = 0; | |||
CRITICAL_BLOCK(wallet.cs_mapRequestCount) | |||
wallet.mapRequestCount[pblock->GetHash()] = 0; | |||
// Process this block the same as if we had received it from another node | |||
if (!ProcessBlock(NULL, pblock)) | |||
@@ -2892,13 +2901,15 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey) | |||
return true; | |||
} | |||
void BitcoinMiner() | |||
void static ThreadBitcoinMiner(void* parg); | |||
void static BitcoinMiner(CWallet *pwallet) | |||
{ | |||
printf("BitcoinMiner started\n"); | |||
SetThreadPriority(THREAD_PRIORITY_LOWEST); | |||
// Each thread has its own key and counter | |||
CReserveKey reservekey; | |||
CReserveKey reservekey(pwallet); | |||
unsigned int nExtraNonce = 0; | |||
int64 nPrevTime = 0; | |||
@@ -2974,7 +2985,7 @@ void BitcoinMiner() | |||
assert(hash == pblock->GetHash()); | |||
SetThreadPriority(THREAD_PRIORITY_NORMAL); | |||
CheckWork(pblock.get(), reservekey); | |||
CheckWork(pblock.get(), *pwalletMain, reservekey); | |||
SetThreadPriority(THREAD_PRIORITY_LOWEST); | |||
break; | |||
} | |||
@@ -3035,12 +3046,13 @@ void BitcoinMiner() | |||
} | |||
} | |||
void ThreadBitcoinMiner(void* parg) | |||
void static ThreadBitcoinMiner(void* parg) | |||
{ | |||
CWallet* pwallet = (CWallet*)parg; | |||
try | |||
{ | |||
vnThreadsRunning[3]++; | |||
BitcoinMiner(); | |||
BitcoinMiner(pwallet); | |||
vnThreadsRunning[3]--; | |||
} | |||
catch (std::exception& e) { | |||
@@ -3058,12 +3070,12 @@ void ThreadBitcoinMiner(void* parg) | |||
} | |||
void GenerateBitcoins(bool fGenerate) | |||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet) | |||
{ | |||
if (fGenerateBitcoins != fGenerate) | |||
{ | |||
fGenerateBitcoins = fGenerate; | |||
CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins); | |||
WriteSetting("fGenerateBitcoins", fGenerateBitcoins); | |||
MainFrameRepaint(); | |||
} | |||
if (fGenerateBitcoins) | |||
@@ -3078,7 +3090,7 @@ void GenerateBitcoins(bool fGenerate) | |||
printf("Starting %d BitcoinMiner threads\n", nAddThreads); | |||
for (int i = 0; i < nAddThreads; i++) | |||
{ | |||
if (!CreateThread(ThreadBitcoinMiner, NULL)) | |||
if (!CreateThread(ThreadBitcoinMiner, pwallet)) | |||
printf("Error: CreateThread(ThreadBitcoinMiner) failed\n"); | |||
Sleep(10); | |||
} |
@@ -8,21 +8,17 @@ | |||
#include "net.h" | |||
#include "key.h" | |||
#include "script.h" | |||
#include "db.h" | |||
#include <list> | |||
class COutPoint; | |||
class CInPoint; | |||
class CDiskTxPos; | |||
class CCoinBase; | |||
class CTxIn; | |||
class CTxOut; | |||
class CTransaction; | |||
class CBlock; | |||
class CBlockIndex; | |||
class CWalletTx; | |||
class CWallet; | |||
class CKeyItem; | |||
class CReserveKey; | |||
class CWalletDB; | |||
class CMessageHeader; | |||
class CAddress; | |||
@@ -62,15 +58,12 @@ extern CBigNum bnBestChainWork; | |||
extern CBigNum bnBestInvalidWork; | |||
extern uint256 hashBestChain; | |||
extern CBlockIndex* pindexBest; | |||
extern std::set<int64> setKeyPool; | |||
extern CCriticalSection cs_setKeyPool; | |||
extern unsigned int nTransactionsUpdated; | |||
extern double dHashesPerSec; | |||
extern int64 nHPSTimerStart; | |||
extern int64 nTimeBestReceived; | |||
extern std::map<std::string, std::string> mapAddressBook; | |||
extern CCriticalSection cs_mapAddressBook; | |||
extern CCriticalSection cs_setpwalletRegistered; | |||
extern std::set<CWallet*> setpwalletRegistered; | |||
// Settings | |||
extern int fGenerateBitcoins; | |||
@@ -90,21 +83,20 @@ class CReserveKey; | |||
class CTxDB; | |||
class CTxIndex; | |||
void RegisterWallet(CWallet* pwalletIn); | |||
void UnregisterWallet(CWallet* pwalletIn); | |||
bool CheckDiskSpace(uint64 nAdditionalBytes=0); | |||
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); | |||
FILE* AppendBlockFile(unsigned int& nFileRet); | |||
bool LoadBlockIndex(bool fAllowNew=true); | |||
void PrintBlockTree(); | |||
bool ProcessMessages(CNode* pfrom); | |||
bool ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv); | |||
bool SendMessages(CNode* pto, bool fSendTrickle); | |||
void GenerateBitcoins(bool fGenerate); | |||
void ThreadBitcoinMiner(void* parg); | |||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet); | |||
CBlock* CreateNewBlock(CReserveKey& reservekey); | |||
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime); | |||
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1); | |||
bool CheckWork(CBlock* pblock, CReserveKey& reservekey); | |||
void BitcoinMiner(); | |||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey); | |||
bool CheckProofOfWork(uint256 hash, unsigned int nBits); | |||
bool IsInitialBlockDownload(); | |||
std::string GetWarnings(std::string strFor); | |||
@@ -120,6 +112,23 @@ std::string GetWarnings(std::string strFor); | |||
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); | |||
template<typename T> | |||
bool WriteSetting(const std::string& strKey, const T& value) | |||
{ | |||
bool fOk = false; | |||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) | |||
{ | |||
std::string strWalletFile; | |||
if (!GetWalletFile(pwallet, strWalletFile)) | |||
continue; | |||
fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value); | |||
} | |||
return fOk; | |||
} | |||
class CDiskTxPos | |||
{ | |||
public: | |||
@@ -302,9 +311,6 @@ public: | |||
{ | |||
printf("%s\n", ToString().c_str()); | |||
} | |||
bool IsMine() const; | |||
int64 GetDebit() const; | |||
}; | |||
@@ -353,36 +359,6 @@ public: | |||
return SerializeHash(*this); | |||
} | |||
bool IsMine() const | |||
{ | |||
return ::IsMine(scriptPubKey); | |||
} | |||
int64 GetCredit() const | |||
{ | |||
if (!MoneyRange(nValue)) | |||
throw std::runtime_error("CTxOut::GetCredit() : value out of range"); | |||
return (IsMine() ? nValue : 0); | |||
} | |||
bool IsChange() const | |||
{ | |||
// On a debit transaction, a txout that's mine but isn't in the address book is change | |||
std::vector<unsigned char> vchPubKey; | |||
if (ExtractPubKey(scriptPubKey, true, vchPubKey)) | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
if (!mapAddressBook.count(PubKeyToAddress(vchPubKey))) | |||
return true; | |||
return false; | |||
} | |||
int64 GetChange() const | |||
{ | |||
if (!MoneyRange(nValue)) | |||
throw std::runtime_error("CTxOut::GetChange() : value out of range"); | |||
return (IsChange() ? nValue : 0); | |||
} | |||
friend bool operator==(const CTxOut& a, const CTxOut& b) | |||
{ | |||
return (a.nValue == b.nValue && | |||
@@ -527,57 +503,6 @@ public: | |||
return true; | |||
} | |||
bool IsMine() const | |||
{ | |||
BOOST_FOREACH(const CTxOut& txout, vout) | |||
if (txout.IsMine()) | |||
return true; | |||
return false; | |||
} | |||
bool IsFromMe() const | |||
{ | |||
return (GetDebit() > 0); | |||
} | |||
int64 GetDebit() const | |||
{ | |||
int64 nDebit = 0; | |||
BOOST_FOREACH(const CTxIn& txin, vin) | |||
{ | |||
nDebit += txin.GetDebit(); | |||
if (!MoneyRange(nDebit)) | |||
throw std::runtime_error("CTransaction::GetDebit() : value out of range"); | |||
} | |||
return nDebit; | |||
} | |||
int64 GetCredit() const | |||
{ | |||
int64 nCredit = 0; | |||
BOOST_FOREACH(const CTxOut& txout, vout) | |||
{ | |||
nCredit += txout.GetCredit(); | |||
if (!MoneyRange(nCredit)) | |||
throw std::runtime_error("CTransaction::GetCredit() : value out of range"); | |||
} | |||
return nCredit; | |||
} | |||
int64 GetChange() const | |||
{ | |||
if (IsCoinBase()) | |||
return 0; | |||
int64 nChange = 0; | |||
BOOST_FOREACH(const CTxOut& txout, vout) | |||
{ | |||
nChange += txout.GetChange(); | |||
if (!MoneyRange(nChange)) | |||
throw std::runtime_error("CTransaction::GetChange() : value out of range"); | |||
} | |||
return nChange; | |||
} | |||
int64 GetValueOut() const | |||
{ | |||
int64 nValueOut = 0; | |||
@@ -1639,9 +1564,9 @@ public: | |||
extern std::map<uint256, CTransaction> mapTransactions; | |||
extern std::map<std::vector<unsigned char>, CPrivKey> mapKeys; | |||
extern std::map<uint160, std::vector<unsigned char> > mapPubKeys; | |||
extern CCriticalSection cs_mapKeys; | |||
extern CCriticalSection cs_mapPubKeys; | |||
#endif |
@@ -1117,7 +1117,7 @@ void MapPort(bool fMapPort) | |||
if (fUseUPnP != fMapPort) | |||
{ | |||
fUseUPnP = fMapPort; | |||
CWalletDB().WriteSetting("fUseUPnP", fUseUPnP); | |||
WriteSetting("fUseUPnP", fUseUPnP); | |||
} | |||
if (fUseUPnP && vnThreadsRunning[5] < 1) | |||
{ | |||
@@ -1698,7 +1698,7 @@ void StartNode(void* parg) | |||
printf("Error: CreateThread(ThreadMessageHandler) failed\n"); | |||
// Generate coins in the background | |||
GenerateBitcoins(fGenerateBitcoins); | |||
GenerateBitcoins(fGenerateBitcoins, pwalletMain); | |||
} | |||
bool StopNode() |
@@ -264,14 +264,14 @@ Value setgenerate(const Array& params, bool fHelp) | |||
{ | |||
int nGenProcLimit = params[1].get_int(); | |||
fLimitProcessors = (nGenProcLimit != -1); | |||
CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors); | |||
WriteSetting("fLimitProcessors", fLimitProcessors); | |||
if (nGenProcLimit != -1) | |||
CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit); | |||
WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit); | |||
if (nGenProcLimit == 0) | |||
fGenerate = false; | |||
} | |||
GenerateBitcoins(fGenerate); | |||
GenerateBitcoins(fGenerate, pwalletMain); | |||
return Value::null; | |||
} | |||
@@ -298,7 +298,7 @@ Value getinfo(const Array& params, bool fHelp) | |||
Object obj; | |||
obj.push_back(Pair("version", (int)VERSION)); | |||
obj.push_back(Pair("balance", ValueFromAmount(GetBalance()))); | |||
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); | |||
obj.push_back(Pair("blocks", (int)nBestHeight)); | |||
obj.push_back(Pair("connections", (int)vNodes.size())); | |||
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); | |||
@@ -307,7 +307,7 @@ Value getinfo(const Array& params, bool fHelp) | |||
obj.push_back(Pair("difficulty", (double)GetDifficulty())); | |||
obj.push_back(Pair("hashespersec", gethashespersec(params, false))); | |||
obj.push_back(Pair("testnet", fTestNet)); | |||
obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime())); | |||
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); | |||
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); | |||
obj.push_back(Pair("errors", GetWarnings("statusbar"))); | |||
return obj; | |||
@@ -329,9 +329,9 @@ Value getnewaddress(const Array& params, bool fHelp) | |||
strAccount = AccountFromValue(params[0]); | |||
// Generate a new key that is added to wallet | |||
string strAddress = PubKeyToAddress(GetKeyFromKeyPool()); | |||
string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool()); | |||
SetAddressBookName(strAddress, strAccount); | |||
pwalletMain->SetAddressBookName(strAddress, strAccount); | |||
return strAddress; | |||
} | |||
@@ -341,7 +341,7 @@ string GetAccountAddress(string strAccount, bool bForceNew=false) | |||
{ | |||
string strAddress; | |||
CWalletDB walletdb; | |||
CWalletDB walletdb(pwalletMain->strWalletFile); | |||
walletdb.TxnBegin(); | |||
CAccount account; | |||
@@ -352,8 +352,8 @@ string GetAccountAddress(string strAccount, bool bForceNew=false) | |||
{ | |||
CScript scriptPubKey; | |||
scriptPubKey.SetBitcoinAddress(account.vchPubKey); | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); | |||
it != mapWallet.end() && !account.vchPubKey.empty(); | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); | |||
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty(); | |||
++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
@@ -366,9 +366,9 @@ string GetAccountAddress(string strAccount, bool bForceNew=false) | |||
// Generate a new key | |||
if (account.vchPubKey.empty() || bForceNew) | |||
{ | |||
account.vchPubKey = GetKeyFromKeyPool(); | |||
account.vchPubKey = pwalletMain->GetKeyFromKeyPool(); | |||
string strAddress = PubKeyToAddress(account.vchPubKey); | |||
SetAddressBookName(strAddress, strAccount); | |||
pwalletMain->SetAddressBookName(strAddress, strAccount); | |||
walletdb.WriteAccount(strAccount, account); | |||
} | |||
@@ -391,7 +391,7 @@ Value getaccountaddress(const Array& params, bool fHelp) | |||
Value ret; | |||
CRITICAL_BLOCK(cs_main) | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
ret = GetAccountAddress(strAccount); | |||
} | |||
@@ -421,18 +421,18 @@ Value setaccount(const Array& params, bool fHelp) | |||
// Detect when changing the account of an address that is the 'unused current key' of another account: | |||
CRITICAL_BLOCK(cs_main) | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
if (mapAddressBook.count(strAddress)) | |||
if (pwalletMain->mapAddressBook.count(strAddress)) | |||
{ | |||
string strOldAccount = mapAddressBook[strAddress]; | |||
string strOldAccount = pwalletMain->mapAddressBook[strAddress]; | |||
if (strAddress == GetAccountAddress(strOldAccount)) | |||
GetAccountAddress(strOldAccount, true); | |||
} | |||
} | |||
SetAddressBookName(strAddress, strAccount); | |||
pwalletMain->SetAddressBookName(strAddress, strAccount); | |||
return Value::null; | |||
} | |||
@@ -447,10 +447,10 @@ Value getaccount(const Array& params, bool fHelp) | |||
string strAddress = params[0].get_str(); | |||
string strAccount; | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
map<string, string>::iterator mi = mapAddressBook.find(strAddress); | |||
if (mi != mapAddressBook.end() && !(*mi).second.empty()) | |||
map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress); | |||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty()) | |||
strAccount = (*mi).second; | |||
} | |||
return strAccount; | |||
@@ -468,9 +468,9 @@ Value getaddressesbyaccount(const Array& params, bool fHelp) | |||
// Find all addresses that have the given account | |||
Array ret; | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook) | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook) | |||
{ | |||
const string& strAddress = item.first; | |||
const string& strName = item.second; | |||
@@ -523,7 +523,7 @@ Value sendtoaddress(const Array& params, bool fHelp) | |||
CRITICAL_BLOCK(cs_main) | |||
{ | |||
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); | |||
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); | |||
if (strError != "") | |||
throw JSONRPCError(-4, strError); | |||
} | |||
@@ -544,7 +544,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) | |||
CScript scriptPubKey; | |||
if (!scriptPubKey.SetBitcoinAddress(strAddress)) | |||
throw JSONRPCError(-5, "Invalid bitcoin address"); | |||
if (!IsMine(scriptPubKey)) | |||
if (!IsMine(*pwalletMain,scriptPubKey)) | |||
return (double)0.0; | |||
// Minimum confirmations | |||
@@ -554,9 +554,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) | |||
// Tally | |||
int64 nAmount = 0; | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
if (wtx.IsCoinBase() || !wtx.IsFinal()) | |||
@@ -575,9 +575,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) | |||
void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey) | |||
{ | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook) | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook) | |||
{ | |||
const string& strAddress = item.first; | |||
const string& strName = item.second; | |||
@@ -586,7 +586,7 @@ void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey) | |||
// We're only counting our own valid bitcoin addresses and not ip addresses | |||
CScript scriptPubKey; | |||
if (scriptPubKey.SetBitcoinAddress(strAddress)) | |||
if (IsMine(scriptPubKey)) | |||
if (IsMine(*pwalletMain,scriptPubKey)) | |||
setPubKey.insert(scriptPubKey); | |||
} | |||
} | |||
@@ -613,9 +613,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) | |||
// Tally | |||
int64 nAmount = 0; | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
if (wtx.IsCoinBase() || !wtx.IsFinal()) | |||
@@ -635,10 +635,10 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) | |||
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth) | |||
{ | |||
int64 nBalance = 0; | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
// Tally wallet transactions | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
if (!wtx.IsFinal()) | |||
@@ -661,7 +661,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD | |||
int64 GetAccountBalance(const string& strAccount, int nMinDepth) | |||
{ | |||
CWalletDB walletdb; | |||
CWalletDB walletdb(pwalletMain->strWalletFile); | |||
return GetAccountBalance(walletdb, strAccount, nMinDepth); | |||
} | |||
@@ -675,7 +675,7 @@ Value getbalance(const Array& params, bool fHelp) | |||
"If [account] is specified, returns the balance in the account."); | |||
if (params.size() == 0) | |||
return ValueFromAmount(GetBalance()); | |||
return ValueFromAmount(pwalletMain->GetBalance()); | |||
int nMinDepth = 1; | |||
if (params.size() > 1) | |||
@@ -686,7 +686,7 @@ Value getbalance(const Array& params, bool fHelp) | |||
// (GetBalance() sums up all unspent TxOuts) | |||
// getbalance and getbalance '*' should always return the same number. | |||
int64 nBalance = 0; | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
if (!wtx.IsFinal()) | |||
@@ -734,9 +734,9 @@ Value movecmd(const Array& params, bool fHelp) | |||
if (params.size() > 4) | |||
strComment = params[4].get_str(); | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
CWalletDB walletdb; | |||
CWalletDB walletdb(pwalletMain->strWalletFile); | |||
walletdb.TxnBegin(); | |||
int64 nNow = GetAdjustedTime(); | |||
@@ -787,7 +787,7 @@ Value sendfrom(const Array& params, bool fHelp) | |||
wtx.mapValue["to"] = params[5].get_str(); | |||
CRITICAL_BLOCK(cs_main) | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
// Check funds | |||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth); | |||
@@ -795,7 +795,7 @@ Value sendfrom(const Array& params, bool fHelp) | |||
throw JSONRPCError(-6, "Account has insufficient funds"); | |||
// Send | |||
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); | |||
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); | |||
if (strError != "") | |||
throw JSONRPCError(-4, strError); | |||
} | |||
@@ -844,7 +844,7 @@ Value sendmany(const Array& params, bool fHelp) | |||
} | |||
CRITICAL_BLOCK(cs_main) | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
// Check funds | |||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth); | |||
@@ -852,16 +852,16 @@ Value sendmany(const Array& params, bool fHelp) | |||
throw JSONRPCError(-6, "Account has insufficient funds"); | |||
// Send | |||
CReserveKey keyChange; | |||
CReserveKey keyChange(pwalletMain); | |||
int64 nFeeRequired = 0; | |||
bool fCreated = CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); | |||
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); | |||
if (!fCreated) | |||
{ | |||
if (totalAmount + nFeeRequired > GetBalance()) | |||
if (totalAmount + nFeeRequired > pwalletMain->GetBalance()) | |||
throw JSONRPCError(-6, "Insufficient funds"); | |||
throw JSONRPCError(-4, "Transaction creation failed"); | |||
} | |||
if (!CommitTransaction(wtx, keyChange)) | |||
if (!pwalletMain->CommitTransaction(wtx, keyChange)) | |||
throw JSONRPCError(-4, "Transaction commit failed"); | |||
} | |||
@@ -894,9 +894,9 @@ Value ListReceived(const Array& params, bool fByAccounts) | |||
// Tally | |||
map<uint160, tallyitem> mapTally; | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
if (wtx.IsCoinBase() || !wtx.IsFinal()) | |||
@@ -923,9 +923,9 @@ Value ListReceived(const Array& params, bool fByAccounts) | |||
// Reply | |||
Array ret; | |||
map<string, tallyitem> mapAccountTally; | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook) | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook) | |||
{ | |||
const string& strAddress = item.first; | |||
const string& strAccount = item.second; | |||
@@ -1061,13 +1061,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe | |||
// Received | |||
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived) | |||
{ | |||
string account; | |||
if (mapAddressBook.count(r.first)) | |||
account = mapAddressBook[r.first]; | |||
if (pwalletMain->mapAddressBook.count(r.first)) | |||
account = pwalletMain->mapAddressBook[r.first]; | |||
if (fAllAccounts || (account == strAccount)) | |||
{ | |||
Object entry; | |||
@@ -1119,16 +1119,16 @@ Value listtransactions(const Array& params, bool fHelp) | |||
nFrom = params[2].get_int(); | |||
Array ret; | |||
CWalletDB walletdb; | |||
CWalletDB walletdb(pwalletMain->strWalletFile); | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
// Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap: | |||
typedef pair<CWalletTx*, CAccountingEntry*> TxPair; | |||
typedef multimap<int64, TxPair > TxItems; | |||
TxItems txByTime; | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
CWalletTx* wtx = &((*it).second); | |||
txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0))); | |||
@@ -1180,16 +1180,16 @@ Value listaccounts(const Array& params, bool fHelp) | |||
nMinDepth = params[0].get_int(); | |||
map<string, int64> mapAccountBalances; | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, mapAddressBook) { | |||
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) { | |||
uint160 hash160; | |||
if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me | |||
mapAccountBalances[entry.second] = 0; | |||
} | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
int64 nGeneratedImmature, nGeneratedMature, nFee; | |||
@@ -1204,8 +1204,8 @@ Value listaccounts(const Array& params, bool fHelp) | |||
{ | |||
mapAccountBalances[""] += nGeneratedMature; | |||
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived) | |||
if (mapAddressBook.count(r.first)) | |||
mapAccountBalances[mapAddressBook[r.first]] += r.second; | |||
if (pwalletMain->mapAddressBook.count(r.first)) | |||
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second; | |||
else | |||
mapAccountBalances[""] += r.second; | |||
} | |||
@@ -1213,7 +1213,7 @@ Value listaccounts(const Array& params, bool fHelp) | |||
} | |||
list<CAccountingEntry> acentries; | |||
CWalletDB().ListAccountCreditDebit("*", acentries); | |||
CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries); | |||
BOOST_FOREACH(const CAccountingEntry& entry, acentries) | |||
mapAccountBalances[entry.strAccount] += entry.nCreditDebit; | |||
@@ -1235,11 +1235,11 @@ Value gettransaction(const Array& params, bool fHelp) | |||
hash.SetHex(params[0].get_str()); | |||
Object entry; | |||
CRITICAL_BLOCK(cs_mapWallet) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
if (!mapWallet.count(hash)) | |||
if (!pwalletMain->mapWallet.count(hash)) | |||
throw JSONRPCError(-5, "Invalid or non-wallet transaction id"); | |||
const CWalletTx& wtx = mapWallet[hash]; | |||
const CWalletTx& wtx = pwalletMain->mapWallet[hash]; | |||
int64 nCredit = wtx.GetCredit(); | |||
int64 nDebit = wtx.GetDebit(); | |||
@@ -1250,10 +1250,10 @@ Value gettransaction(const Array& params, bool fHelp) | |||
if (wtx.IsFromMe()) | |||
entry.push_back(Pair("fee", ValueFromAmount(nFee))); | |||
WalletTxToJSON(mapWallet[hash], entry); | |||
WalletTxToJSON(pwalletMain->mapWallet[hash], entry); | |||
Array details; | |||
ListTransactions(mapWallet[hash], "*", 0, false, details); | |||
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details); | |||
entry.push_back(Pair("details", details)); | |||
} | |||
@@ -1269,7 +1269,7 @@ Value backupwallet(const Array& params, bool fHelp) | |||
"Safely copies wallet.dat to destination, which can be a directory or a path with filename."); | |||
string strDest = params[0].get_str(); | |||
BackupWallet(strDest); | |||
BackupWallet(*pwalletMain, strDest); | |||
return Value::null; | |||
} | |||
@@ -1295,10 +1295,10 @@ Value validateaddress(const Array& params, bool fHelp) | |||
string currentAddress = Hash160ToAddress(hash160); | |||
ret.push_back(Pair("address", currentAddress)); | |||
ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0))); | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
if (mapAddressBook.count(currentAddress)) | |||
ret.push_back(Pair("account", mapAddressBook[currentAddress])); | |||
if (pwalletMain->mapAddressBook.count(currentAddress)) | |||
ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress])); | |||
} | |||
} | |||
return ret; | |||
@@ -1325,7 +1325,7 @@ Value getwork(const Array& params, bool fHelp) | |||
static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock; | |||
static vector<CBlock*> vNewBlock; | |||
static CReserveKey reservekey; | |||
static CReserveKey reservekey(pwalletMain); | |||
if (params.size() == 0) | |||
{ | |||
@@ -1406,7 +1406,7 @@ Value getwork(const Array& params, bool fHelp) | |||
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce); | |||
pblock->hashMerkleRoot = pblock->BuildMerkleTree(); | |||
return CheckWork(pblock, reservekey); | |||
return CheckWork(pblock, *pwalletMain, reservekey); | |||
} | |||
} | |||
@@ -1021,7 +1021,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo | |||
} | |||
bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet) | |||
bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet) | |||
{ | |||
scriptSigRet.clear(); | |||
@@ -1030,7 +1030,7 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s | |||
return false; | |||
// Compile solution | |||
CRITICAL_BLOCK(cs_mapKeys) | |||
CRITICAL_BLOCK(keystore.cs_mapKeys) | |||
{ | |||
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution) | |||
{ | |||
@@ -1038,12 +1038,12 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s | |||
{ | |||
// Sign | |||
const valtype& vchPubKey = item.second; | |||
if (!mapKeys.count(vchPubKey)) | |||
if (!keystore.HaveKey(vchPubKey)) | |||
return false; | |||
if (hash != 0) | |||
{ | |||
vector<unsigned char> vchSig; | |||
if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig)) | |||
if (!CKey::Sign(keystore.GetPrivKey(vchPubKey), hash, vchSig)) | |||
return false; | |||
vchSig.push_back((unsigned char)nHashType); | |||
scriptSigRet << vchSig; | |||
@@ -1056,12 +1056,12 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s | |||
if (mi == mapPubKeys.end()) | |||
return false; | |||
const vector<unsigned char>& vchPubKey = (*mi).second; | |||
if (!mapKeys.count(vchPubKey)) | |||
if (!keystore.HaveKey(vchPubKey)) | |||
return false; | |||
if (hash != 0) | |||
{ | |||
vector<unsigned char> vchSig; | |||
if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig)) | |||
if (!CKey::Sign(keystore.GetPrivKey(vchPubKey), hash, vchSig)) | |||
return false; | |||
vchSig.push_back((unsigned char)nHashType); | |||
scriptSigRet << vchSig << vchPubKey; | |||
@@ -1085,14 +1085,14 @@ bool IsStandard(const CScript& scriptPubKey) | |||
} | |||
bool IsMine(const CScript& scriptPubKey) | |||
bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) | |||
{ | |||
CScript scriptSig; | |||
return Solver(scriptPubKey, 0, 0, scriptSig); | |||
return Solver(keystore, scriptPubKey, 0, 0, scriptSig); | |||
} | |||
bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet) | |||
bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* keystore, vector<unsigned char>& vchPubKeyRet) | |||
{ | |||
vchPubKeyRet.clear(); | |||
@@ -1100,7 +1100,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned | |||
if (!Solver(scriptPubKey, vSolution)) | |||
return false; | |||
CRITICAL_BLOCK(cs_mapKeys) | |||
CRITICAL_BLOCK(cs_mapPubKeys) | |||
{ | |||
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution) | |||
{ | |||
@@ -1116,7 +1116,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned | |||
continue; | |||
vchPubKey = (*mi).second; | |||
} | |||
if (!fMineOnly || mapKeys.count(vchPubKey)) | |||
if (keystore == NULL || keystore->HaveKey(vchPubKey)) | |||
{ | |||
vchPubKeyRet = vchPubKey; | |||
return true; | |||
@@ -1160,7 +1160,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C | |||
} | |||
bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq) | |||
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq) | |||
{ | |||
assert(nIn < txTo.vin.size()); | |||
CTxIn& txin = txTo.vin[nIn]; | |||
@@ -1171,7 +1171,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int | |||
// The checksig op will also drop the signatures from its hash. | |||
uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType); | |||
if (!Solver(txout.scriptPubKey, hash, nHashType, txin.scriptSig)) | |||
if (!Solver(keystore, txout.scriptPubKey, hash, nHashType, txin.scriptSig)) | |||
return false; | |||
txin.scriptSig = scriptPrereq + txin.scriptSig; | |||
@@ -1199,10 +1199,5 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig | |||
if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType)) | |||
return false; | |||
// Anytime a signature is successfully verified, it's proof the outpoint is spent, | |||
// so lets update the wallet spent flag if it doesn't know due to wallet.dat being | |||
// restored from backup or the user making copies of wallet.dat. | |||
WalletUpdateSpent(txin.prevout); | |||
return true; | |||
} |
@@ -708,12 +708,11 @@ public: | |||
uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); | |||
bool IsStandard(const CScript& scriptPubKey); | |||
bool IsMine(const CScript& scriptPubKey); | |||
bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, std::vector<unsigned char>& vchPubKeyRet); | |||
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); | |||
bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* pkeystore, std::vector<unsigned char>& vchPubKeyRet); | |||
bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret); | |||
bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript()); | |||
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript()); | |||
bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0); | |||
#endif |
@@ -240,7 +240,7 @@ void SetDefaultReceivingAddress(const string& strAddress) | |||
return; | |||
if (!mapPubKeys.count(hash160)) | |||
return; | |||
CWalletDB().WriteDefaultKey(mapPubKeys[hash160]); | |||
CWalletDB(pwalletMain->strWalletFile).WriteDefaultKey(mapPubKeys[hash160]); | |||
pframeMain->m_textCtrlAddress->SetValue(strAddress); | |||
} | |||
} | |||
@@ -290,7 +290,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) | |||
dResize = 1.22; | |||
SetSize(dResize * GetSize().GetWidth(), 1.15 * GetSize().GetHeight()); | |||
#endif | |||
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " "); | |||
m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + " "); | |||
m_listCtrl->SetFocus(); | |||
ptaskbaricon = new CMyTaskBarIcon(); | |||
#ifdef __WXMAC_OSX__ | |||
@@ -330,7 +330,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) | |||
// Fill your address text box | |||
vector<unsigned char> vchPubKey; | |||
if (CWalletDB("r").ReadDefaultKey(vchPubKey)) | |||
if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey)) | |||
m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey)); | |||
// Fill listctrl with wallet transactions | |||
@@ -625,7 +625,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) | |||
{ | |||
int64 nUnmatured = 0; | |||
BOOST_FOREACH(const CTxOut& txout, wtx.vout) | |||
nUnmatured += txout.GetCredit(); | |||
nUnmatured += pwalletMain->GetCredit(txout); | |||
if (wtx.IsInMainChain()) | |||
{ | |||
strDescription = strprintf(_("Generated (%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity()); | |||
@@ -661,19 +661,19 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) | |||
return false; | |||
BOOST_FOREACH(const CTxOut& txout, wtx.vout) | |||
{ | |||
if (txout.IsMine()) | |||
if (pwalletMain->IsMine(txout)) | |||
{ | |||
vector<unsigned char> vchPubKey; | |||
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) | |||
if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey)) | |||
{ | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
{ | |||
//strDescription += _("Received payment to "); | |||
//strDescription += _("Received with address "); | |||
strDescription += _("Received with: "); | |||
string strAddress = PubKeyToAddress(vchPubKey); | |||
map<string, string>::iterator mi = mapAddressBook.find(strAddress); | |||
if (mi != mapAddressBook.end() && !(*mi).second.empty()) | |||
map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress); | |||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty()) | |||
{ | |||
string strLabel = (*mi).second; | |||
strDescription += strAddress.substr(0,12) + "... "; | |||
@@ -703,11 +703,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) | |||
{ | |||
bool fAllFromMe = true; | |||
BOOST_FOREACH(const CTxIn& txin, wtx.vin) | |||
fAllFromMe = fAllFromMe && txin.IsMine(); | |||
fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin); | |||
bool fAllToMe = true; | |||
BOOST_FOREACH(const CTxOut& txout, wtx.vout) | |||
fAllToMe = fAllToMe && txout.IsMine(); | |||
fAllToMe = fAllToMe && pwalletMain->IsMine(txout); | |||
if (fAllFromMe && fAllToMe) | |||
{ | |||
@@ -733,7 +733,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) | |||
for (int nOut = 0; nOut < wtx.vout.size(); nOut++) | |||
{ | |||
const CTxOut& txout = wtx.vout[nOut]; | |||
if (txout.IsMine()) | |||
if (pwalletMain->IsMine(txout)) | |||
continue; | |||
string strAddress; | |||
@@ -751,9 +751,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) | |||
} | |||
string strDescription = _("To: "); | |||
CRITICAL_BLOCK(cs_mapAddressBook) | |||
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty()) | |||
strDescription += mapAddressBook[strAddress] + " "; | |||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) | |||
if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty()) | |||
strDescription += pwalletMain->mapAddressBook[strAddress] + " "; | |||
strDescription += strAddress; | |||
if (!mapValue["message"].empty()) | |||
{ | |||
@@ -792,9 +792,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) | |||
// | |||
bool fAllMine = true; | |||
BOOST_FOREACH(const CTxOut& txout, wtx.vout) | |||
fAllMine = fAllMine && txout.IsMine(); | |||
fAllMine = fAllMine && pwalletMain->IsMine(txout); | |||
BOOST_FOREACH(const CTxIn& txin, wtx.vin) | |||
fAllMine = fAllMine && txin.IsMine(); | |||
fAllMine = fAllMine && pwalletMain->IsMine(txin); | |||
InsertLine(fNew, nIndex, hash, strSort, colour, | |||
strStatus, | |||
@@ -821,16 +821,16 @@ void CMainFrame::OnIdle(wxIdleEvent& event) | |||
// Collect list of wallet transactions and sort newest first | |||
bool fEntered = false; | |||
vector<pair<unsigned int, uint256> > vSorted; | |||
TRY_CRITICAL_BLOCK(cs_mapWallet) | |||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
printf("RefreshListCtrl starting\n"); | |||
fEntered = true; | |||
fRefreshListCtrl = false; | |||
vWalletUpdated.clear(); | |||
pwalletMain->vWalletUpdated.clear(); | |||
// Do the newest transactions first | |||
vSorted.reserve(mapWallet.size()); | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
vSorted.reserve(pwalletMain->mapWallet.size()); | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
const CWalletTx& wtx = (*it).second; | |||
unsigned int nTime = UINT_MAX - wtx.GetTxTime(); | |||
@@ -849,12 +849,12 @@ void CMainFrame::OnIdle(wxIdleEvent& event) | |||
if (fShutdown) | |||
return; | |||
bool fEntered = false; | |||
TRY_CRITICAL_BLOCK(cs_mapWallet) | |||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
fEntered = true; | |||
uint256& hash = vSorted[i++].second; | |||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); | |||
if (mi != mapWallet.end()) | |||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash); | |||
if (mi != pwalletMain->mapWallet.end()) | |||
InsertTransaction((*mi).second, true); | |||
} | |||
if (!fEntered || i == 100 || i % 500 == 0) | |||
@@ -872,10 +872,10 @@ void CMainFrame::OnIdle(wxIdleEvent& event) | |||
static int64 nLastTime; | |||
if (GetTime() > nLastTime + 30) | |||
{ | |||
TRY_CRITICAL_BLOCK(cs_mapWallet) | |||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
nLastTime = GetTime(); | |||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) | |||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) | |||
{ | |||
CWalletTx& wtx = (*it).second; | |||
if (wtx.nTimeDisplayed && wtx.nTimeDisplayed != wtx.GetTxTime()) | |||
@@ -896,7 +896,7 @@ void CMainFrame::RefreshStatusColumn() | |||
if (nTop == nLastTop && pindexLastBest == pindexBest) | |||
return; | |||
TRY_CRITICAL_BLOCK(cs_mapWallet) | |||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
int nStart = nTop; | |||
int nEnd = min(nStart + 100, m_listCtrl->GetItemCount()); | |||
@@ -916,8 +916,8 @@ void CMainFrame::RefreshStatusColumn() | |||
for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++) | |||
{ | |||
uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1)); | |||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); | |||
if (mi == mapWallet.end()) | |||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash); | |||
if (mi == pwalletMain->mapWallet.end()) | |||
{ | |||
printf("CMainFrame::RefreshStatusColumn() : tx not found in mapWallet\n"); | |||
continue; | |||
@@ -1014,41 +1014,41 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) | |||
nLastRepaintTime = GetTimeMillis(); | |||
// Update listctrl contents | |||
if (!vWalletUpdated.empty()) | |||
if (!pwalletMain->vWalletUpdated.empty()) | |||
{ | |||
TRY_CRITICAL_BLOCK(cs_mapWallet) | |||
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet) | |||
{ | |||
string strTop; | |||
if (m_listCtrl->GetItemCount()) | |||
strTop = (string)m_listCtrl->GetItemText(0); | |||
BOOST_FOREACH(uint256 hash, vWalletUpdated) | |||
BOOST_FOREACH(uint256 hash, pwalletMain->vWalletUpdated) | |||
{ | |||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); | |||
if (mi != mapWallet.end()) | |||
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash); | |||
if (mi != pwalletMain->mapWallet.end()) | |||
InsertTransaction((*mi).second, false); | |||
} | |||
vWalletUpdated.clear(); | |||
pwalletMain->vWalletUpdated.clear(); | |||