22 #include <boost/thread.hpp> 30 return WriteIC(std::make_pair(std::string(
"name"), strAddress), strName);
37 return EraseIC(std::make_pair(std::string(
"name"), strAddress));
42 return WriteIC(std::make_pair(std::string(
"purpose"), strAddress), strPurpose);
47 return EraseIC(std::make_pair(std::string(
"purpose"), strAddress));
52 return WriteIC(std::make_pair(std::string(
"tx"), wtx.
GetHash()), wtx);
57 return EraseIC(std::make_pair(std::string(
"tx"), hash));
62 if (!
WriteIC(std::make_pair(std::string(
"keymeta"), vchPubKey), keyMeta,
false)) {
67 std::vector<unsigned char> vchKey;
68 vchKey.reserve(vchPubKey.
size() + vchPrivKey.size());
69 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
70 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
72 return WriteIC(std::make_pair(std::string(
"key"), vchPubKey), std::make_pair(vchPrivKey,
Hash(vchKey.begin(), vchKey.end())),
false);
76 const std::vector<unsigned char>& vchCryptedSecret,
79 if (!
WriteIC(std::make_pair(std::string(
"keymeta"), vchPubKey), keyMeta)) {
83 if (!
WriteIC(std::make_pair(std::string(
"ckey"), vchPubKey), vchCryptedSecret,
false)) {
86 EraseIC(std::make_pair(std::string(
"key"), vchPubKey));
87 EraseIC(std::make_pair(std::string(
"wkey"), vchPubKey));
93 return WriteIC(std::make_pair(std::string(
"mkey"), nID), kMasterKey,
true);
98 return WriteIC(std::make_pair(std::string(
"cscript"), hash), redeemScript,
false);
103 if (!
WriteIC(std::make_pair(std::string(
"watchmeta"), dest), keyMeta)) {
106 return WriteIC(std::make_pair(std::string(
"watchs"), dest),
'1');
111 if (!
EraseIC(std::make_pair(std::string(
"watchmeta"), dest))) {
114 return EraseIC(std::make_pair(std::string(
"watchs"), dest));
120 return WriteIC(std::string(
"bestblock_nomerkle"), locator);
125 if (
m_batch.
Read(std::string(
"bestblock"), locator) && !locator.
vHave.empty())
return true;
126 return m_batch.
Read(std::string(
"bestblock_nomerkle"), locator);
131 return WriteIC(std::string(
"orderposnext"), nOrderPosNext);
136 return m_batch.
Read(std::make_pair(std::string(
"pool"), nPool), keypool);
141 return WriteIC(std::make_pair(std::string(
"pool"), nPool), keypool);
146 return EraseIC(std::make_pair(std::string(
"pool"), nPool));
151 return WriteIC(std::string(
"minversion"), nVersion);
183 if (strType ==
"name")
185 std::string strAddress;
189 else if (strType ==
"purpose")
191 std::string strAddress;
195 else if (strType ==
"tx")
199 CWalletTx wtx(
nullptr , MakeTransactionRef());
206 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
208 if (!ssValue.empty())
212 std::string unused_string;
213 ssValue >> fTmp >> fUnused >> unused_string;
214 strErr =
strprintf(
"LoadWallet() upgrading tx ver=%d %d %s",
215 wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
216 wtx.fTimeReceivedIsTxTime = fTmp;
220 strErr =
strprintf(
"LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
221 wtx.fTimeReceivedIsTxTime = 0;
223 wss.vWalletUpgrade.push_back(hash);
226 if (wtx.nOrderPos == -1)
227 wss.fAnyUnordered =
true;
229 pwallet->LoadToWallet(wtx);
231 else if (strType ==
"watchs")
239 pwallet->LoadWatchOnly(script);
241 else if (strType ==
"key" || strType ==
"wkey")
245 if (!vchPubKey.IsValid())
247 strErr =
"Error reading wallet database: CPubKey corrupt";
254 if (strType ==
"key")
275 bool fSkipCheck =
false;
280 std::vector<unsigned char> vchKey;
281 vchKey.reserve(vchPubKey.size() + pkey.size());
282 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
283 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
285 if (
Hash(vchKey.begin(), vchKey.end()) != hash)
287 strErr =
"Error reading wallet database: CPubKey/CPrivKey corrupt";
294 if (!key.
Load(pkey, vchPubKey, fSkipCheck))
296 strErr =
"Error reading wallet database: CPrivKey corrupt";
299 if (!pwallet->LoadKey(key, vchPubKey))
301 strErr =
"Error reading wallet database: LoadKey failed";
305 else if (strType ==
"mkey")
310 ssValue >> kMasterKey;
311 if(pwallet->mapMasterKeys.count(nID) != 0)
313 strErr =
strprintf(
"Error reading wallet database: duplicate CMasterKey id %u", nID);
316 pwallet->mapMasterKeys[nID] = kMasterKey;
317 if (pwallet->nMasterKeyMaxID < nID)
318 pwallet->nMasterKeyMaxID = nID;
320 else if (strType ==
"ckey")
324 if (!vchPubKey.IsValid())
326 strErr =
"Error reading wallet database: CPubKey corrupt";
329 std::vector<unsigned char> vchPrivKey;
330 ssValue >> vchPrivKey;
333 if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
335 strErr =
"Error reading wallet database: LoadCryptedKey failed";
338 wss.fIsEncrypted =
true;
340 else if (strType ==
"keymeta")
347 pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);
349 else if (strType ==
"watchmeta")
356 pwallet->LoadScriptMetadata(
CScriptID(script), keyMeta);
358 else if (strType ==
"defaultkey")
363 ssValue >> vchPubKey;
364 if (!vchPubKey.IsValid()) {
365 strErr =
"Error reading wallet database: Default Key corrupt";
369 else if (strType ==
"pool")
376 pwallet->LoadKeyPool(nIndex, keypool);
378 else if (strType ==
"version")
380 ssValue >> wss.nFileVersion;
381 if (wss.nFileVersion == 10300)
382 wss.nFileVersion = 300;
384 else if (strType ==
"cscript")
390 if (!pwallet->LoadCScript(script))
392 strErr =
"Error reading wallet database: LoadCScript failed";
396 else if (strType ==
"orderposnext")
398 ssValue >> pwallet->nOrderPosNext;
400 else if (strType ==
"destdata")
402 std::string strAddress, strKey, strValue;
408 else if (strType ==
"hdchain")
412 pwallet->SetHDChain(chain,
true);
413 }
else if (strType ==
"flags") {
416 if (!pwallet->SetWalletFlags(
flags,
true)) {
417 strErr =
"Error reading wallet database: Unknown non-tolerable wallet flags found";
420 }
else if (strType !=
"bestblock" && strType !=
"bestblock_nomerkle" &&
421 strType !=
"minversion" && strType !=
"acentry") {
422 wss.m_unknown_records++;
433 return (strType==
"key" || strType ==
"wkey" ||
434 strType ==
"mkey" || strType ==
"ckey");
440 bool fNoncriticalErrors =
false;
446 if (
m_batch.
Read((std::string)
"minversion", nMinVersion))
467 if (
ret == DB_NOTFOUND)
471 pwallet->
WalletLogPrintf(
"Error reading next record from wallet database\n");
476 std::string strType, strErr;
477 if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
481 if (
IsKeyType(strType) || strType ==
"defaultkey") {
483 }
else if(strType ==
"flags") {
488 fNoncriticalErrors =
true;
499 catch (
const boost::thread_interrupted&) {
516 pwallet->
WalletLogPrintf(
"Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
524 WriteTx(pwallet->mapWallet.at(hash));
545 if (
m_batch.
Read((std::string)
"minversion", nMinVersion))
555 LogPrintf(
"Error getting wallet database cursor\n");
565 if (
ret == DB_NOTFOUND)
569 LogPrintf(
"Error reading next record from wallet database\n");
575 if (strType ==
"tx") {
579 CWalletTx wtx(
nullptr , MakeTransactionRef());
582 vTxHash.push_back(hash);
588 catch (
const boost::thread_interrupted&) {
601 std::vector<uint256> vTxHash;
602 std::vector<CWalletTx> vWtx;
608 std::sort(vTxHash.begin(), vTxHash.end());
609 std::sort(vTxHashIn.begin(), vTxHashIn.end());
612 bool delerror =
false;
613 std::vector<uint256>::iterator it = vTxHashIn.begin();
614 for (
const uint256& hash : vTxHash) {
615 while (it < vTxHashIn.end() && (*it) < hash) {
618 if (it == vTxHashIn.end()) {
621 else if ((*it) == hash) {
623 LogPrint(
BCLog::DB,
"Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
626 vTxHashOut.push_back(hash);
639 std::vector<uint256> vTxHash;
645 for (
const uint256& hash : vTxHash) {
655 static std::atomic<bool> fOneThread(
false);
656 if (fOneThread.exchange(
true)) {
663 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets()) {
702 std::string strType, strErr;
707 fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
708 dummyWss, strType, strErr);
710 if (!
IsKeyType(strType) && strType !=
"hdchain")
714 LogPrintf(
"WARNING: WalletBatch::Recover skipping %s: %s\n", strType, strErr);
733 return WriteIC(std::make_pair(std::string(
"destdata"), std::make_pair(address, key)), value);
738 return EraseIC(std::make_pair(std::string(
"destdata"), std::make_pair(address, key)));
744 return WriteIC(std::string(
"hdchain"), chain);
bool TxnCommit()
Commit current transaction.
bool WriteName(const std::string &strAddress, const std::string &strName)
bool EraseIC(const K &key)
bool WriteVersion(int nVersion)
Write wallet version.
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
bool ErasePurpose(const std::string &strAddress)
bool ReadBestBlock(CBlockLocator &locator)
std::vector< std::shared_ptr< CWallet > > GetWallets()
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
const uint256 & GetHash() const
bool WriteIC(const K &key, const T &value, bool fOverwrite=true)
DBErrors FindWalletTx(std::vector< uint256 > &vTxHash, std::vector< CWalletTx > &vWtx)
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
bool WriteMinVersion(int nVersion)
UniValue ret(UniValue::VARR)
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
std::vector< uint256 > vWalletUpgrade
static bool VerifyDatabaseFile(const fs::path &wallet_path, std::string &warningStr, std::string &errorStr)
An instance of this class represents one database.
unsigned int m_unknown_records
bool TxnBegin()
Begin a new transaction.
Double ended buffer combining vector and stream-like interfaces.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
DBErrors ZapWalletTx(std::vector< CWalletTx > &vWtx)
bool WriteTx(const CWalletTx &wtx)
DBErrors LoadWallet(CWallet *pwallet)
DBErrors
Error statuses for the wallet database.
static bool PeriodicFlush(BerkeleyDatabase &database)
bool WriteWalletFlags(const uint64_t flags)
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
const unsigned char * begin() const
static bool Recover(const fs::path &wallet_path, void *callbackDataIn, bool(*recoverKVcallback)(void *callbackData, CDataStream ssKey, CDataStream ssValue), std::string &out_backup_filename)
bool EraseWatchOnly(const CScript &script)
bool WriteBestBlock(const CBlockLocator &locator)
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
secure_allocator is defined in allocators.h CPrivKey is a serialized private key, with all parameters...
bool TxnAbort()
Abort current transaction.
DBErrors ReorderTransactions()
bool Read(const K &key, T &value)
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
static bool IsKeyType(const std::string &strType)
const unsigned char * end() const
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Update wallet first key creation time.
static bool VerifyEnvironment(const fs::path &wallet_path, std::string &errorStr)
An encapsulated public key.
bool WriteVersion(int nVersion)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
bool WriteOrderPosNext(int64_t nOrderPosNext)
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
std::vector< uint256 > vHave
CCriticalSection cs_wallet
static bool VerifyEnvironment(const fs::path &file_path, std::string &errorStr)
static bool Recover(const fs::path &file_path, void *callbackDataIn, bool(*recoverKVcallback)(void *callbackData, CDataStream ssKey, CDataStream ssValue), std::string &out_backup_filename)
A transaction with a bunch of additional info that only the owner cares about.
bool ErasePool(int64_t nPool)
bool WritePool(int64_t nPool, const CKeyPool &keypool)
Capture information about block/transaction validation.
CTxDestination DecodeDestination(const std::string &str)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t nLastWalletUpdate
Serialized script, used inside transaction inputs and outputs.
unsigned int nLastFlushed
int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue, bool setRange=false)
Private key that includes an expiration date in case it never gets used.
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
std::atomic< unsigned int > nUpdateCounter
bool CheckTransaction(const CTransaction &tx, CValidationState &state, bool fCheckDuplicateInputs)
Transaction validation functions.
bool ReadPool(int64_t nPool, CKeyPool &keypool)
A reference to a CScript: the Hash360 of its serialization (see script.h)
bool ReadVersion(int &nVersion)
bool ReadVersion(int &nVersion)
Read wallet version.
static bool VerifyDatabaseFile(const fs::path &file_path, std::string &warningStr, std::string &errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
An encapsulated private key.
bool EraseTx(uint256 hash)
static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
bool EraseName(const std::string &strAddress)