unsigned int nWalletDBUpdated;
-
+uint64 nAccountingEntryNumber = 0;
DB_INIT_MPOOL |
DB_INIT_TXN |
DB_THREAD |
- DB_PRIVATE |
DB_RECOVER,
S_IRUSR | S_IWUSR);
if (ret > 0)
// Flush database activity from memory pool to disk log
unsigned int nMinutes = 0;
+ if (fReadOnly)
+ nMinutes = 1;
if (strFile == "addr.dat")
nMinutes = 2;
if (strFile == "blkindex.dat" && IsInitialBlockDownload() && nBestHeight % 500 != 0)
CBlockIndex* pindexFork = NULL;
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
{
- if (pindex->nHeight < 74000 && !mapArgs.count("-checkblocks"))
+ if (pindex->nHeight < nBestHeight-2500 && !mapArgs.count("-checkblocks"))
break;
CBlock block;
if (!block.ReadFromDisk(pindex))
return Write(make_pair(string("addr"), addr.GetKey()), addr);
}
+bool CAddrDB::EraseAddress(const CAddress& addr)
+{
+ return Erase(make_pair(string("addr"), addr.GetKey()));
+}
+
bool CAddrDB::LoadAddresses()
{
CRITICAL_BLOCK(cs_mapAddresses)
pcursor->close();
printf("Loaded %d addresses\n", mapAddresses.size());
-
- // Fix for possible bug that manifests in mapAddresses.count in irc.cpp,
- // just need to call count here and it doesn't happen there. The bug was the
- // pack pragma in irc.cpp and has been fixed, but I'm not in a hurry to delete this.
- mapAddresses.count(vector<unsigned char>(18));
}
return true;
// CWalletDB
//
+static set<int64> setKeyPool;
+static CCriticalSection cs_setKeyPool;
+
+bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
+{
+ account.SetNull();
+ return Read(make_pair(string("acc"), strAccount), account);
+}
+
+bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
+{
+ return Write(make_pair(string("acc"), strAccount), account);
+}
+
+bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
+{
+ return Write(make_tuple(string("acentry"), acentry.strAccount, ++nAccountingEntryNumber), acentry);
+}
+
+int64 CWalletDB::GetAccountCreditDebit(const string& strAccount)
+{
+ list<CAccountingEntry> entries;
+ ListAccountCreditDebit(strAccount, entries);
+
+ int64 nCreditDebit = 0;
+ foreach (const CAccountingEntry& entry, entries)
+ nCreditDebit += entry.nCreditDebit;
+
+ return nCreditDebit;
+}
+
+void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
+{
+ int64 nCreditDebit = 0;
+
+ bool fAllAccounts = (strAccount == "*");
+
+ Dbc* pcursor = GetCursor();
+ if (!pcursor)
+ throw runtime_error("CWalletDB::ListAccountCreditDebit() : cannot create DB cursor");
+ unsigned int fFlags = DB_SET_RANGE;
+ loop
+ {
+ // Read next record
+ CDataStream ssKey;
+ if (fFlags == DB_SET_RANGE)
+ ssKey << make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64(0));
+ CDataStream ssValue;
+ int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
+ fFlags = DB_NEXT;
+ if (ret == DB_NOTFOUND)
+ break;
+ else if (ret != 0)
+ {
+ pcursor->close();
+ throw runtime_error("CWalletDB::ListAccountCreditDebit() : error scanning DB");
+ }
+
+ // Unserialize
+ string strType;
+ ssKey >> strType;
+ if (strType != "acentry")
+ break;
+ CAccountingEntry acentry;
+ ssKey >> acentry.strAccount;
+ if (!fAllAccounts && acentry.strAccount != strAccount)
+ break;
+
+ ssValue >> acentry;
+ entries.push_back(acentry);
+ }
+
+ pcursor->close();
+}
+
+
bool CWalletDB::LoadWallet()
{
vchDefaultKey.clear();
int nFileVersion = 0;
+ vector<uint256> vWalletUpgrade;
// Modify defaults
#ifndef __WXMSW__
#endif
//// todo: shouldn't we catch exceptions and try to recover and continue?
- CRITICAL_BLOCK(cs_mapKeys)
CRITICAL_BLOCK(cs_mapWallet)
+ CRITICAL_BLOCK(cs_mapKeys)
{
// Get cursor
Dbc* pcursor = GetCursor();
if (wtx.GetHash() != hash)
printf("Error in wallet.dat, hash mismatch\n");
+ // Undo serialize changes in 31600
+ if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
+ {
+ if (!ssValue.empty())
+ {
+ char fTmp;
+ char fUnused;
+ ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
+ printf("LoadWallet() upgrading tx ver=%d %d '%s' %s\n", wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount.c_str(), hash.ToString().c_str());
+ wtx.fTimeReceivedIsTxTime = fTmp;
+ }
+ else
+ {
+ printf("LoadWallet() repairing tx ver=%d %s\n", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str());
+ wtx.fTimeReceivedIsTxTime = 0;
+ }
+ vWalletUpgrade.push_back(hash);
+ }
+
//// debug print
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
//printf(" %12I64d %s %s %s\n",
// wtx.hashBlock.ToString().substr(0,20).c_str(),
// wtx.mapValue["message"].c_str());
}
+ else if (strType == "acentry")
+ {
+ string strAccount;
+ ssKey >> strAccount;
+ uint64 nNumber;
+ ssKey >> nNumber;
+ if (nNumber > nAccountingEntryNumber)
+ nAccountingEntryNumber = nNumber;
+ }
else if (strType == "key" || strType == "wkey")
{
vector<unsigned char> vchPubKey;
{
ssValue >> vchDefaultKey;
}
+ else if (strType == "pool")
+ {
+ int64 nIndex;
+ ssKey >> nIndex;
+ setKeyPool.insert(nIndex);
+ }
else if (strType == "version")
{
ssValue >> nFileVersion;
if (strKey == "fMinimizeOnClose") ssValue >> fMinimizeOnClose;
if (strKey == "fUseProxy") ssValue >> fUseProxy;
if (strKey == "addrProxy") ssValue >> addrProxy;
-
+ if (fHaveUPnP && strKey == "fUseUPnP") ssValue >> fUseUPnP;
}
}
pcursor->close();
}
+ foreach(uint256 hash, vWalletUpgrade)
+ WriteTx(hash, mapWallet[hash]);
+
printf("nFileVersion = %d\n", nFileVersion);
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
printf("nTransactionFee = %"PRI64d"\n", nTransactionFee);
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
printf("fUseProxy = %d\n", fUseProxy);
printf("addrProxy = %s\n", addrProxy.ToString().c_str());
+ if (fHaveUPnP)
+ printf("fUseUPnP = %d\n", fUseUPnP);
- // The transaction fee setting won't be needed for many years to come.
- // Setting it to zero here in case they set it to something in an earlier version.
- if (nTransactionFee != 0)
- {
- nTransactionFee = 0;
- WriteSetting("nTransactionFee", nTransactionFee);
- }
-
// Upgrade
if (nFileVersion < VERSION)
{
WriteVersion(VERSION);
}
+
return true;
}
keyUser.MakeNewKey();
if (!AddKey(keyUser))
return false;
- if (!SetAddressBookName(PubKeyToAddress(keyUser.GetPubKey()), "Your Address"))
+ if (!SetAddressBookName(PubKeyToAddress(keyUser.GetPubKey()), ""))
return false;
CWalletDB().WriteDefaultKey(keyUser.GetPubKey());
}
Sleep(100);
}
}
+
+
+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;
+}