14 #include <boost/filesystem.hpp>
15 #include <boost/foreach.hpp>
18 using namespace boost;
30 return Write(make_pair(
string(
"name"), strAddress), strName);
38 return Erase(make_pair(
string(
"name"), strAddress));
44 return Write(make_pair(
string(
"purpose"), strAddress), strPurpose);
50 return Erase(make_pair(
string(
"purpose"), strPurpose));
56 return Write(std::make_pair(std::string(
"tx"), hash), wtx);
62 return Erase(std::make_pair(std::string(
"tx"), hash));
69 if (!Write(std::make_pair(std::string(
"keymeta"), vchPubKey),
74 std::vector<unsigned char> vchKey;
75 vchKey.reserve(vchPubKey.
size() + vchPrivKey.size());
76 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
77 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
79 return Write(std::make_pair(std::string(
"key"), vchPubKey), std::make_pair(vchPrivKey,
Hash(vchKey.begin(), vchKey.end())),
false);
83 const std::vector<unsigned char>& vchCryptedSecret,
86 const bool fEraseUnencryptedKey =
true;
89 if (!Write(std::make_pair(std::string(
"keymeta"), vchPubKey),
93 if (!Write(std::make_pair(std::string(
"ckey"), vchPubKey), vchCryptedSecret,
false))
95 if (fEraseUnencryptedKey)
97 Erase(std::make_pair(std::string(
"key"), vchPubKey));
98 Erase(std::make_pair(std::string(
"wkey"), vchPubKey));
106 return Write(std::make_pair(std::string(
"mkey"), nID), kMasterKey,
true);
112 return Write(std::make_pair(std::string(
"cscript"), hash), redeemScript,
false);
118 return Write(std::string(
"bestblock"), locator);
123 return Read(std::string(
"bestblock"), locator);
129 return Write(std::string(
"orderposnext"), nOrderPosNext);
135 return Write(std::string(
"defaultkey"), vchPubKey);
140 return Read(std::make_pair(std::string(
"pool"), nPool), keypool);
146 return Write(std::make_pair(std::string(
"pool"), nPool), keypool);
152 return Erase(std::make_pair(std::string(
"pool"), nPool));
157 return Write(std::string(
"minversion"), nVersion);
163 return Read(make_pair(
string(
"acc"), strAccount), account);
168 return Write(make_pair(
string(
"acc"), strAccount), account);
173 return Write(boost::make_tuple(
string(
"acentry"), acentry.
strAccount, nAccEntryNum), acentry);
183 list<CAccountingEntry> entries;
184 ListAccountCreditDebit(strAccount, entries);
186 int64_t nCreditDebit = 0;
195 bool fAllAccounts = (strAccount ==
"*");
197 Dbc* pcursor = GetCursor();
199 throw runtime_error(
"CWalletDB::ListAccountCreditDebit() : cannot create DB cursor");
200 unsigned int fFlags = DB_SET_RANGE;
205 if (fFlags == DB_SET_RANGE)
206 ssKey << boost::make_tuple(
string(
"acentry"), (fAllAccounts?
string(
"") : strAccount), uint64_t(0));
208 int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
210 if (ret == DB_NOTFOUND)
215 throw runtime_error(
"CWalletDB::ListAccountCreditDebit() : error scanning DB");
221 if (strType !=
"acentry")
225 if (!fAllAccounts && acentry.
strAccount != strAccount)
229 ssKey >> acentry.nEntryNo;
230 entries.push_back(acentry);
245 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
246 typedef multimap<int64_t, TxPair > TxItems;
249 for (map<uint256, CWalletTx>::iterator it = pwallet->
mapWallet.begin(); it != pwallet->
mapWallet.end(); ++it)
254 list<CAccountingEntry> acentries;
255 ListAccountCreditDebit(
"", acentries);
258 txByTime.insert(make_pair(entry.
nTime, TxPair((
CWalletTx*)0, &entry)));
263 std::vector<int64_t> nOrderPosOffsets;
264 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
266 CWalletTx *
const pwtx = (*it).second.first;
272 nOrderPos = nOrderPosNext++;
273 nOrderPosOffsets.push_back(nOrderPos);
277 if (!WriteAccountingEntry(pacentry->
nEntryNo, *pacentry))
282 int64_t nOrderPosOff = 0;
283 BOOST_FOREACH(
const int64_t& nOffsetStart, nOrderPosOffsets)
285 if (nOrderPos >= nOffsetStart)
288 nOrderPos += nOrderPosOff;
289 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
297 if (!WriteTx(pwtx->
GetHash(), *pwtx))
301 if (!WriteAccountingEntry(pacentry->
nEntryNo, *pacentry))
320 nKeys = nCKeys = nKeyMeta = 0;
321 fIsEncrypted =
false;
322 fAnyUnordered =
false;
336 if (strType ==
"name")
342 else if (strType ==
"purpose")
348 else if (strType ==
"tx")
359 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
361 if (!ssValue.
empty())
365 ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
366 strErr =
strprintf(
"LoadWallet() upgrading tx ver=%d %d '%s' %s",
367 wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount, hash.ToString());
368 wtx.fTimeReceivedIsTxTime = fTmp;
372 strErr =
strprintf(
"LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
373 wtx.fTimeReceivedIsTxTime = 0;
378 if (wtx.nOrderPos == -1)
390 else if (strType ==
"acentry")
403 if (acentry.nOrderPos == -1)
407 else if (strType ==
"key" || strType ==
"wkey")
411 if (!vchPubKey.IsValid())
413 strErr =
"Error reading wallet database: CPubKey corrupt";
420 if (strType ==
"key")
441 bool fSkipCheck =
false;
446 std::vector<unsigned char> vchKey;
447 vchKey.reserve(vchPubKey.size() + pkey.size());
448 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
449 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
451 if (
Hash(vchKey.begin(), vchKey.end()) != hash)
453 strErr =
"Error reading wallet database: CPubKey/CPrivKey corrupt";
460 if (!key.
Load(pkey, vchPubKey, fSkipCheck))
462 strErr =
"Error reading wallet database: CPrivKey corrupt";
465 if (!pwallet->
LoadKey(key, vchPubKey))
467 strErr =
"Error reading wallet database: LoadKey failed";
471 else if (strType ==
"mkey")
476 ssValue >> kMasterKey;
479 strErr =
strprintf(
"Error reading wallet database: duplicate CMasterKey id %u", nID);
486 else if (strType ==
"ckey")
488 vector<unsigned char> vchPubKey;
490 vector<unsigned char> vchPrivKey;
491 ssValue >> vchPrivKey;
496 strErr =
"Error reading wallet database: LoadCryptedKey failed";
501 else if (strType ==
"keymeta")
516 else if (strType ==
"defaultkey")
520 else if (strType ==
"pool")
531 CKeyID keyid = keypool.vchPubKey.GetID();
535 else if (strType ==
"version")
541 else if (strType ==
"cscript")
549 strErr =
"Error reading wallet database: LoadCScript failed";
553 else if (strType ==
"orderposnext")
557 else if (strType ==
"destdata")
559 std::string strAddress, strKey, strValue;
565 strErr =
"Error reading wallet database: LoadDestData failed";
578 return (strType==
"key" || strType ==
"wkey" ||
579 strType ==
"mkey" || strType ==
"ckey");
586 bool fNoncriticalErrors =
false;
592 if (Read((
string)
"minversion", nMinVersion))
600 Dbc* pcursor = GetCursor();
603 LogPrintf(
"Error getting wallet database cursor\n");
612 int ret = ReadAtCursor(pcursor, ssKey, ssValue);
613 if (ret == DB_NOTFOUND)
617 LogPrintf(
"Error reading next record from wallet database\n");
622 string strType, strErr;
623 if (!
ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
632 fNoncriticalErrors =
true;
643 catch (boost::thread_interrupted) {
650 if (fNoncriticalErrors && result ==
DB_LOAD_OK)
660 LogPrintf(
"Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
678 result = ReorderTransactions(pwallet);
687 bool fNoncriticalErrors =
false;
693 if (Read((
string)
"minversion", nMinVersion))
701 Dbc* pcursor = GetCursor();
704 LogPrintf(
"Error getting wallet database cursor\n");
713 int ret = ReadAtCursor(pcursor, ssKey, ssValue);
714 if (ret == DB_NOTFOUND)
718 LogPrintf(
"Error reading next record from wallet database\n");
724 if (strType ==
"tx") {
728 vTxHash.push_back(hash);
733 catch (boost::thread_interrupted) {
740 if (fNoncriticalErrors && result ==
DB_LOAD_OK)
749 vector<uint256> vTxHash;
750 DBErrors err = FindWalletTx(pwallet, vTxHash);
755 BOOST_FOREACH (
uint256& hash, vTxHash) {
768 static bool fOneThread;
777 int64_t nLastWalletUpdate =
GetTime();
798 nRefCount += (*mi).second;
804 boost::this_thread::interruption_point();
808 LogPrint(
"db",
"Flushing wallet.dat\n");
842 filesystem::path pathDest(strDest);
843 if (filesystem::is_directory(pathDest))
847 #if BOOST_VERSION >= 104000
848 filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
850 filesystem::copy_file(pathSrc, pathDest);
852 LogPrintf(
"copied wallet.dat to %s\n", pathDest.string());
854 }
catch(
const filesystem::filesystem_error &e) {
855 LogPrintf(
"error copying wallet.dat to %s - %s\n", pathDest.string(), e.what());
878 std::string newFilename =
strprintf(
"wallet.%d.bak", now);
880 int result = dbenv.
dbenv.dbrename(NULL, filename.c_str(), NULL,
881 newFilename.c_str(), DB_AUTO_COMMIT);
883 LogPrintf(
"Renamed %s to %s\n", filename, newFilename);
886 LogPrintf(
"Failed to rename %s to %s\n", filename, newFilename);
890 std::vector<CDBEnv::KeyValPair> salvagedData;
891 bool allOK = dbenv.
Salvage(newFilename,
true, salvagedData);
892 if (salvagedData.empty())
894 LogPrintf(
"Salvage(aggressive) found no records in %s.\n", newFilename);
897 LogPrintf(
"Salvage(aggressive) found %u records\n", salvagedData.size());
899 bool fSuccess = allOK;
900 Db* pdbCopy =
new Db(&dbenv.
dbenv, 0);
901 int ret = pdbCopy->open(NULL,
909 LogPrintf(
"Cannot create database file %s\n", filename);
922 string strType, strErr;
923 bool fReadOK =
ReadKeyValue(&dummyWallet, ssKey, ssValue,
924 wss, strType, strErr);
929 LogPrintf(
"WARNING: CWalletDB::Recover skipping %s: %s\n", strType, strErr);
933 Dbt datKey(&row.first[0], row.first.size());
934 Dbt datValue(&row.second[0], row.second.size());
935 int ret2 = pdbCopy->put(ptxn, &datKey, &datValue, DB_NOOVERWRITE);
954 return Write(boost::make_tuple(std::string(
"destdata"), address, key), value);
960 return Erase(boost::make_tuple(
string(
"destdata"), address, key));
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
unsigned int nWalletDBUpdated
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret)
bool WriteMinVersion(int nVersion)
std::set< int64_t > setKeyPool
std::map< std::string, int > mapFileUseCount
bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
Adds a destination data tuple to the store, without saving it to disk.
DBErrors FindWalletTx(CWallet *pwallet, std::vector< uint256 > &vTxHash)
void CheckpointLSN(std::string strFile)
bool WriteAccount(const std::string &strAccount, const CAccount &account)
DbTxn * TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
#define TRY_LOCK(cs, name)
bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata)
std::map< CTxDestination, CAddressBookData > mapAddressBook
CCriticalSection cs_wallet
Main wallet lock.
void MilliSleep(int64_t n)
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Master key for wallet encryption.
unsigned int size() const
static const int CLIENT_VERSION
void ListAccountCreditDebit(const std::string &strAccount, std::list< CAccountingEntry > &acentries)
Double ended buffer combining vector and stream-like interfaces.
base58-encoded Bitcoin addresses.
bool ErasePurpose(const std::string &strAddress)
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry &acentry)
bool BackupWallet(const CWallet &wallet, const string &strDest)
DBErrors
Error statuses for the wallet database.
CTxDestination Get() const
void RenameThread(const char *name)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool EraseTx(uint256 hash)
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
DBErrors ZapWalletTx(CWallet *pwallet)
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
unsigned int nMasterKeyMaxID
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
bool WritePool(int64_t nPool, const CKeyPool &keypool)
int64_t GetAccountCreditDebit(const std::string &strAccount)
static int LogPrint(const char *category, const char *format)
bool WriteName(const std::string &strAddress, const std::string &strName)
DBErrors LoadWallet(CWallet *pwallet)
An encapsulated public key.
bool LoadKey(const CKey &key, const CPubKey &pubkey)
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
uint256 Hash(const T1 pbegin, const T1 pend)
bool LoadCScript(const CScript &redeemScript)
bool ErasePool(int64_t nPool)
vector< uint256 > vWalletUpgrade
bool WriteTx(uint256 hash, const CWalletTx &wtx)
bool LoadMinVersion(int nVersion)
const unsigned char * begin() const
bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck)
A transaction with a bunch of additional info that only the owner cares about.
DBErrors ReorderTransactions(CWallet *)
std::string strWalletFile
bool ReadBestBlock(CBlockLocator &locator)
bool WriteDefaultKey(const CPubKey &vchPubKey)
Capture information about block/transaction validation.
bool WriteBestBlock(const CBlockLocator &locator)
void ThreadFlushWalletDB(const string &strFile)
bool Salvage(std::string strFile, bool fAggressive, std::vector< KeyValPair > &vResult)
MasterKeyMap mapMasterKeys
static bool IsKeyType(string strType)
bool ReadPool(int64_t nPool, CKeyPool &keypool)
Serialized script, used inside transaction inputs and outputs.
static uint64_t nAccountingEntryNumber
void CloseDb(const std::string &strFile)
static bool Recover(CDBEnv &dbenv, std::string filename, bool fOnlyKeys)
Private key that includes an expiration date in case it never gets used.
A reference to a CKey: the Hash160 of its serialized public key.
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
std::map< CKeyID, CKeyMetadata > mapKeyMetadata
bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue, CWalletScanState &wss, string &strType, string &strErr)
std::map< uint256, CWalletTx > mapWallet
bool AddToWallet(const CWalletTx &wtxIn, bool fFromLoadWallet=false)
unsigned int nTimeReceived
An encapsulated private key.
bool EraseName(const std::string &strAddress)
std::pair< std::vector< unsigned char >, std::vector< unsigned char > > KeyValPair
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool ReadAccount(const std::string &strAccount, CAccount &account)
bool CheckTransaction(const CTransaction &tx, CValidationState &state)
const unsigned char * end() const
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)