1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include "wallet/walletdb.h"
9 #include "consensus/tx_verify.h"
10 #include "consensus/validation.h"
13 #include "serialize.h"
17 #include "wallet/wallet.h"
21 #include <boost/thread.hpp>
27 bool CWalletDB::WriteName(const std::string
& strAddress
, const std::string
& strName
)
29 return WriteIC(std::make_pair(std::string("name"), strAddress
), strName
);
32 bool CWalletDB::EraseName(const std::string
& strAddress
)
34 // This should only be used for sending addresses, never for receiving addresses,
35 // receiving addresses must always have an address book entry if they're not change return.
36 return EraseIC(std::make_pair(std::string("name"), strAddress
));
39 bool CWalletDB::WritePurpose(const std::string
& strAddress
, const std::string
& strPurpose
)
41 return WriteIC(std::make_pair(std::string("purpose"), strAddress
), strPurpose
);
44 bool CWalletDB::ErasePurpose(const std::string
& strPurpose
)
46 return EraseIC(std::make_pair(std::string("purpose"), strPurpose
));
49 bool CWalletDB::WriteTx(const CWalletTx
& wtx
)
51 return WriteIC(std::make_pair(std::string("tx"), wtx
.GetHash()), wtx
);
54 bool CWalletDB::EraseTx(uint256 hash
)
56 return EraseIC(std::make_pair(std::string("tx"), hash
));
59 bool CWalletDB::WriteKey(const CPubKey
& vchPubKey
, const CPrivKey
& vchPrivKey
, const CKeyMetadata
& keyMeta
)
61 if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey
), keyMeta
, false)) {
65 // hash pubkey/privkey to accelerate wallet load
66 std::vector
<unsigned char> vchKey
;
67 vchKey
.reserve(vchPubKey
.size() + vchPrivKey
.size());
68 vchKey
.insert(vchKey
.end(), vchPubKey
.begin(), vchPubKey
.end());
69 vchKey
.insert(vchKey
.end(), vchPrivKey
.begin(), vchPrivKey
.end());
71 return WriteIC(std::make_pair(std::string("key"), vchPubKey
), std::make_pair(vchPrivKey
, Hash(vchKey
.begin(), vchKey
.end())), false);
74 bool CWalletDB::WriteCryptedKey(const CPubKey
& vchPubKey
,
75 const std::vector
<unsigned char>& vchCryptedSecret
,
76 const CKeyMetadata
&keyMeta
)
78 if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey
), keyMeta
)) {
82 if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey
), vchCryptedSecret
, false)) {
85 EraseIC(std::make_pair(std::string("key"), vchPubKey
));
86 EraseIC(std::make_pair(std::string("wkey"), vchPubKey
));
90 bool CWalletDB::WriteMasterKey(unsigned int nID
, const CMasterKey
& kMasterKey
)
92 return WriteIC(std::make_pair(std::string("mkey"), nID
), kMasterKey
, true);
95 bool CWalletDB::WriteCScript(const uint160
& hash
, const CScript
& redeemScript
)
97 return WriteIC(std::make_pair(std::string("cscript"), hash
), redeemScript
, false);
100 bool CWalletDB::WriteWatchOnly(const CScript
&dest
, const CKeyMetadata
& keyMeta
)
102 if (!WriteIC(std::make_pair(std::string("watchmeta"), dest
), keyMeta
)) {
105 return WriteIC(std::make_pair(std::string("watchs"), dest
), '1');
108 bool CWalletDB::EraseWatchOnly(const CScript
&dest
)
110 if (!EraseIC(std::make_pair(std::string("watchmeta"), dest
))) {
113 return EraseIC(std::make_pair(std::string("watchs"), dest
));
116 bool CWalletDB::WriteBestBlock(const CBlockLocator
& locator
)
118 WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
119 return WriteIC(std::string("bestblock_nomerkle"), locator
);
122 bool CWalletDB::ReadBestBlock(CBlockLocator
& locator
)
124 if (batch
.Read(std::string("bestblock"), locator
) && !locator
.vHave
.empty()) return true;
125 return batch
.Read(std::string("bestblock_nomerkle"), locator
);
128 bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext
)
130 return WriteIC(std::string("orderposnext"), nOrderPosNext
);
133 bool CWalletDB::WriteDefaultKey(const CPubKey
& vchPubKey
)
135 return WriteIC(std::string("defaultkey"), vchPubKey
);
138 bool CWalletDB::ReadPool(int64_t nPool
, CKeyPool
& keypool
)
140 return batch
.Read(std::make_pair(std::string("pool"), nPool
), keypool
);
143 bool CWalletDB::WritePool(int64_t nPool
, const CKeyPool
& keypool
)
145 return WriteIC(std::make_pair(std::string("pool"), nPool
), keypool
);
148 bool CWalletDB::ErasePool(int64_t nPool
)
150 return EraseIC(std::make_pair(std::string("pool"), nPool
));
153 bool CWalletDB::WriteMinVersion(int nVersion
)
155 return WriteIC(std::string("minversion"), nVersion
);
158 bool CWalletDB::ReadAccount(const std::string
& strAccount
, CAccount
& account
)
161 return batch
.Read(std::make_pair(std::string("acc"), strAccount
), account
);
164 bool CWalletDB::WriteAccount(const std::string
& strAccount
, const CAccount
& account
)
166 return WriteIC(std::make_pair(std::string("acc"), strAccount
), account
);
169 bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum
, const CAccountingEntry
& acentry
)
171 return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry
.strAccount
, nAccEntryNum
)), acentry
);
174 CAmount
CWalletDB::GetAccountCreditDebit(const std::string
& strAccount
)
176 std::list
<CAccountingEntry
> entries
;
177 ListAccountCreditDebit(strAccount
, entries
);
179 CAmount nCreditDebit
= 0;
180 for (const CAccountingEntry
& entry
: entries
)
181 nCreditDebit
+= entry
.nCreditDebit
;
186 void CWalletDB::ListAccountCreditDebit(const std::string
& strAccount
, std::list
<CAccountingEntry
>& entries
)
188 bool fAllAccounts
= (strAccount
== "*");
190 Dbc
* pcursor
= batch
.GetCursor();
192 throw std::runtime_error(std::string(__func__
) + ": cannot create DB cursor");
193 bool setRange
= true;
197 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
199 ssKey
<< std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts
? std::string("") : strAccount
), uint64_t(0)));
200 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
201 int ret
= batch
.ReadAtCursor(pcursor
, ssKey
, ssValue
, setRange
);
203 if (ret
== DB_NOTFOUND
)
208 throw std::runtime_error(std::string(__func__
) + ": error scanning DB");
214 if (strType
!= "acentry")
216 CAccountingEntry acentry
;
217 ssKey
>> acentry
.strAccount
;
218 if (!fAllAccounts
&& acentry
.strAccount
!= strAccount
)
222 ssKey
>> acentry
.nEntryNo
;
223 entries
.push_back(acentry
);
229 class CWalletScanState
{
233 unsigned int nWatchKeys
;
234 unsigned int nKeyMeta
;
238 std::vector
<uint256
> vWalletUpgrade
;
241 nKeys
= nCKeys
= nWatchKeys
= nKeyMeta
= 0;
242 fIsEncrypted
= false;
243 fAnyUnordered
= false;
249 ReadKeyValue(CWallet
* pwallet
, CDataStream
& ssKey
, CDataStream
& ssValue
,
250 CWalletScanState
&wss
, std::string
& strType
, std::string
& strErr
)
254 // Taking advantage of the fact that pair serialization
255 // is just the two items serialized one after the other
257 if (strType
== "name")
259 std::string strAddress
;
261 ssValue
>> pwallet
->mapAddressBook
[CBitcoinAddress(strAddress
).Get()].name
;
263 else if (strType
== "purpose")
265 std::string strAddress
;
267 ssValue
>> pwallet
->mapAddressBook
[CBitcoinAddress(strAddress
).Get()].purpose
;
269 else if (strType
== "tx")
275 CValidationState state
;
276 if (!(CheckTransaction(wtx
, state
) && (wtx
.GetHash() == hash
) && state
.IsValid()))
279 // Undo serialize changes in 31600
280 if (31404 <= wtx
.fTimeReceivedIsTxTime
&& wtx
.fTimeReceivedIsTxTime
<= 31703)
282 if (!ssValue
.empty())
286 ssValue
>> fTmp
>> fUnused
>> wtx
.strFromAccount
;
287 strErr
= strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s",
288 wtx
.fTimeReceivedIsTxTime
, fTmp
, wtx
.strFromAccount
, hash
.ToString());
289 wtx
.fTimeReceivedIsTxTime
= fTmp
;
293 strErr
= strprintf("LoadWallet() repairing tx ver=%d %s", wtx
.fTimeReceivedIsTxTime
, hash
.ToString());
294 wtx
.fTimeReceivedIsTxTime
= 0;
296 wss
.vWalletUpgrade
.push_back(hash
);
299 if (wtx
.nOrderPos
== -1)
300 wss
.fAnyUnordered
= true;
302 pwallet
->LoadToWallet(wtx
);
304 else if (strType
== "acentry")
306 std::string strAccount
;
310 if (nNumber
> pwallet
->nAccountingEntryNumber
) {
311 pwallet
->nAccountingEntryNumber
= nNumber
;
314 if (!wss
.fAnyUnordered
)
316 CAccountingEntry acentry
;
318 if (acentry
.nOrderPos
== -1)
319 wss
.fAnyUnordered
= true;
322 else if (strType
== "watchs")
330 pwallet
->LoadWatchOnly(script
);
332 else if (strType
== "key" || strType
== "wkey")
336 if (!vchPubKey
.IsValid())
338 strErr
= "Error reading wallet database: CPubKey corrupt";
345 if (strType
== "key")
352 pkey
= wkey
.vchPrivKey
;
355 // Old wallets store keys as "key" [pubkey] => [privkey]
356 // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
357 // using EC operations as a checksum.
358 // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
359 // remaining backwards-compatible.
366 bool fSkipCheck
= false;
370 // hash pubkey/privkey to accelerate wallet load
371 std::vector
<unsigned char> vchKey
;
372 vchKey
.reserve(vchPubKey
.size() + pkey
.size());
373 vchKey
.insert(vchKey
.end(), vchPubKey
.begin(), vchPubKey
.end());
374 vchKey
.insert(vchKey
.end(), pkey
.begin(), pkey
.end());
376 if (Hash(vchKey
.begin(), vchKey
.end()) != hash
)
378 strErr
= "Error reading wallet database: CPubKey/CPrivKey corrupt";
385 if (!key
.Load(pkey
, vchPubKey
, fSkipCheck
))
387 strErr
= "Error reading wallet database: CPrivKey corrupt";
390 if (!pwallet
->LoadKey(key
, vchPubKey
))
392 strErr
= "Error reading wallet database: LoadKey failed";
396 else if (strType
== "mkey")
400 CMasterKey kMasterKey
;
401 ssValue
>> kMasterKey
;
402 if(pwallet
->mapMasterKeys
.count(nID
) != 0)
404 strErr
= strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID
);
407 pwallet
->mapMasterKeys
[nID
] = kMasterKey
;
408 if (pwallet
->nMasterKeyMaxID
< nID
)
409 pwallet
->nMasterKeyMaxID
= nID
;
411 else if (strType
== "ckey")
415 if (!vchPubKey
.IsValid())
417 strErr
= "Error reading wallet database: CPubKey corrupt";
420 std::vector
<unsigned char> vchPrivKey
;
421 ssValue
>> vchPrivKey
;
424 if (!pwallet
->LoadCryptedKey(vchPubKey
, vchPrivKey
))
426 strErr
= "Error reading wallet database: LoadCryptedKey failed";
429 wss
.fIsEncrypted
= true;
431 else if (strType
== "keymeta" || strType
== "watchmeta")
433 CTxDestination keyID
;
434 if (strType
== "keymeta")
438 keyID
= vchPubKey
.GetID();
440 else if (strType
== "watchmeta")
444 keyID
= CScriptID(script
);
447 CKeyMetadata keyMeta
;
451 pwallet
->LoadKeyMetadata(keyID
, keyMeta
);
453 else if (strType
== "defaultkey")
455 ssValue
>> pwallet
->vchDefaultKey
;
457 else if (strType
== "pool")
464 pwallet
->LoadKeyPool(nIndex
, keypool
);
466 else if (strType
== "version")
468 ssValue
>> wss
.nFileVersion
;
469 if (wss
.nFileVersion
== 10300)
470 wss
.nFileVersion
= 300;
472 else if (strType
== "cscript")
478 if (!pwallet
->LoadCScript(script
))
480 strErr
= "Error reading wallet database: LoadCScript failed";
484 else if (strType
== "orderposnext")
486 ssValue
>> pwallet
->nOrderPosNext
;
488 else if (strType
== "destdata")
490 std::string strAddress
, strKey
, strValue
;
494 if (!pwallet
->LoadDestData(CBitcoinAddress(strAddress
).Get(), strKey
, strValue
))
496 strErr
= "Error reading wallet database: LoadDestData failed";
500 else if (strType
== "hdchain")
504 if (!pwallet
->SetHDChain(chain
, true))
506 strErr
= "Error reading wallet database: SetHDChain failed";
517 bool CWalletDB::IsKeyType(const std::string
& strType
)
519 return (strType
== "key" || strType
== "wkey" ||
520 strType
== "mkey" || strType
== "ckey");
523 DBErrors
CWalletDB::LoadWallet(CWallet
* pwallet
)
525 pwallet
->vchDefaultKey
= CPubKey();
526 CWalletScanState wss
;
527 bool fNoncriticalErrors
= false;
528 DBErrors result
= DB_LOAD_OK
;
530 LOCK(pwallet
->cs_wallet
);
533 if (batch
.Read((std::string
)"minversion", nMinVersion
))
535 if (nMinVersion
> CLIENT_VERSION
)
537 pwallet
->LoadMinVersion(nMinVersion
);
541 Dbc
* pcursor
= batch
.GetCursor();
544 LogPrintf("Error getting wallet database cursor\n");
551 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
552 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
553 int ret
= batch
.ReadAtCursor(pcursor
, ssKey
, ssValue
);
554 if (ret
== DB_NOTFOUND
)
558 LogPrintf("Error reading next record from wallet database\n");
562 // Try to be tolerant of single corrupt records:
563 std::string strType
, strErr
;
564 if (!ReadKeyValue(pwallet
, ssKey
, ssValue
, wss
, strType
, strErr
))
566 // losing keys is considered a catastrophic error, anything else
567 // we assume the user can live with:
568 if (IsKeyType(strType
))
572 // Leave other errors alone, if we try to fix them we might make things worse.
573 fNoncriticalErrors
= true; // ... but do warn the user there is something wrong.
575 // Rescan if there is a bad transaction record:
576 gArgs
.SoftSetBoolArg("-rescan", true);
580 LogPrintf("%s\n", strErr
);
584 catch (const boost::thread_interrupted
&) {
591 if (fNoncriticalErrors
&& result
== DB_LOAD_OK
)
592 result
= DB_NONCRITICAL_ERROR
;
594 // Any wallet corruption at all: skip any rewriting or
595 // upgrading, we don't want to make it worse.
596 if (result
!= DB_LOAD_OK
)
599 LogPrintf("nFileVersion = %d\n", wss
.nFileVersion
);
601 LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
602 wss
.nKeys
, wss
.nCKeys
, wss
.nKeyMeta
, wss
.nKeys
+ wss
.nCKeys
);
604 // nTimeFirstKey is only reliable if all keys have metadata
605 if ((wss
.nKeys
+ wss
.nCKeys
+ wss
.nWatchKeys
) != wss
.nKeyMeta
)
606 pwallet
->UpdateTimeFirstKey(1);
608 for (uint256 hash
: wss
.vWalletUpgrade
)
609 WriteTx(pwallet
->mapWallet
[hash
]);
611 // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
612 if (wss
.fIsEncrypted
&& (wss
.nFileVersion
== 40000 || wss
.nFileVersion
== 50000))
613 return DB_NEED_REWRITE
;
615 if (wss
.nFileVersion
< CLIENT_VERSION
) // Update
616 WriteVersion(CLIENT_VERSION
);
618 if (wss
.fAnyUnordered
)
619 result
= pwallet
->ReorderTransactions();
621 pwallet
->laccentries
.clear();
622 ListAccountCreditDebit("*", pwallet
->laccentries
);
623 for (CAccountingEntry
& entry
: pwallet
->laccentries
) {
624 pwallet
->wtxOrdered
.insert(make_pair(entry
.nOrderPos
, CWallet::TxPair((CWalletTx
*)0, &entry
)));
630 DBErrors
CWalletDB::FindWalletTx(std::vector
<uint256
>& vTxHash
, std::vector
<CWalletTx
>& vWtx
)
632 bool fNoncriticalErrors
= false;
633 DBErrors result
= DB_LOAD_OK
;
637 if (batch
.Read((std::string
)"minversion", nMinVersion
))
639 if (nMinVersion
> CLIENT_VERSION
)
644 Dbc
* pcursor
= batch
.GetCursor();
647 LogPrintf("Error getting wallet database cursor\n");
654 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
655 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
656 int ret
= batch
.ReadAtCursor(pcursor
, ssKey
, ssValue
);
657 if (ret
== DB_NOTFOUND
)
661 LogPrintf("Error reading next record from wallet database\n");
667 if (strType
== "tx") {
674 vTxHash
.push_back(hash
);
680 catch (const boost::thread_interrupted
&) {
687 if (fNoncriticalErrors
&& result
== DB_LOAD_OK
)
688 result
= DB_NONCRITICAL_ERROR
;
693 DBErrors
CWalletDB::ZapSelectTx(std::vector
<uint256
>& vTxHashIn
, std::vector
<uint256
>& vTxHashOut
)
695 // build list of wallet TXs and hashes
696 std::vector
<uint256
> vTxHash
;
697 std::vector
<CWalletTx
> vWtx
;
698 DBErrors err
= FindWalletTx(vTxHash
, vWtx
);
699 if (err
!= DB_LOAD_OK
) {
703 std::sort(vTxHash
.begin(), vTxHash
.end());
704 std::sort(vTxHashIn
.begin(), vTxHashIn
.end());
706 // erase each matching wallet TX
707 bool delerror
= false;
708 std::vector
<uint256
>::iterator it
= vTxHashIn
.begin();
709 for (uint256 hash
: vTxHash
) {
710 while (it
< vTxHashIn
.end() && (*it
) < hash
) {
713 if (it
== vTxHashIn
.end()) {
716 else if ((*it
) == hash
) {
718 LogPrint(BCLog::DB
, "Transaction was found for deletion but returned database error: %s\n", hash
.GetHex());
721 vTxHashOut
.push_back(hash
);
731 DBErrors
CWalletDB::ZapWalletTx(std::vector
<CWalletTx
>& vWtx
)
733 // build list of wallet TXs
734 std::vector
<uint256
> vTxHash
;
735 DBErrors err
= FindWalletTx(vTxHash
, vWtx
);
736 if (err
!= DB_LOAD_OK
)
739 // erase each wallet TX
740 for (uint256
& hash
: vTxHash
) {
748 void MaybeCompactWalletDB()
750 static std::atomic
<bool> fOneThread(false);
751 if (fOneThread
.exchange(true)) {
754 if (!gArgs
.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET
)) {
758 for (CWalletRef pwallet
: vpwallets
) {
759 CWalletDBWrapper
& dbh
= pwallet
->GetDBHandle();
761 unsigned int nUpdateCounter
= dbh
.nUpdateCounter
;
763 if (dbh
.nLastSeen
!= nUpdateCounter
) {
764 dbh
.nLastSeen
= nUpdateCounter
;
765 dbh
.nLastWalletUpdate
= GetTime();
768 if (dbh
.nLastFlushed
!= nUpdateCounter
&& GetTime() - dbh
.nLastWalletUpdate
>= 2) {
769 if (CDB::PeriodicFlush(dbh
)) {
770 dbh
.nLastFlushed
= nUpdateCounter
;
779 // Try to (very carefully!) recover wallet file if there is a problem.
781 bool CWalletDB::Recover(const std::string
& filename
, void *callbackDataIn
, bool (*recoverKVcallback
)(void* callbackData
, CDataStream ssKey
, CDataStream ssValue
), std::string
& out_backup_filename
)
783 return CDB::Recover(filename
, callbackDataIn
, recoverKVcallback
, out_backup_filename
);
786 bool CWalletDB::Recover(const std::string
& filename
, std::string
& out_backup_filename
)
788 // recover without a key filter callback
789 // results in recovering all record types
790 return CWalletDB::Recover(filename
, nullptr, nullptr, out_backup_filename
);
793 bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData
, CDataStream ssKey
, CDataStream ssValue
)
795 CWallet
*dummyWallet
= reinterpret_cast<CWallet
*>(callbackData
);
796 CWalletScanState dummyWss
;
797 std::string strType
, strErr
;
800 // Required in LoadKeyMetadata():
801 LOCK(dummyWallet
->cs_wallet
);
802 fReadOK
= ReadKeyValue(dummyWallet
, ssKey
, ssValue
,
803 dummyWss
, strType
, strErr
);
805 if (!IsKeyType(strType
) && strType
!= "hdchain")
809 LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType
, strErr
);
816 bool CWalletDB::VerifyEnvironment(const std::string
& walletFile
, const fs::path
& dataDir
, std::string
& errorStr
)
818 return CDB::VerifyEnvironment(walletFile
, dataDir
, errorStr
);
821 bool CWalletDB::VerifyDatabaseFile(const std::string
& walletFile
, const fs::path
& dataDir
, std::string
& warningStr
, std::string
& errorStr
)
823 return CDB::VerifyDatabaseFile(walletFile
, dataDir
, warningStr
, errorStr
, CWalletDB::Recover
);
826 bool CWalletDB::WriteDestData(const std::string
&address
, const std::string
&key
, const std::string
&value
)
828 return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address
, key
)), value
);
831 bool CWalletDB::EraseDestData(const std::string
&address
, const std::string
&key
)
833 return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address
, key
)));
837 bool CWalletDB::WriteHDChain(const CHDChain
& chain
)
839 return WriteIC(std::string("hdchain"), chain
);
842 bool CWalletDB::TxnBegin()
844 return batch
.TxnBegin();
847 bool CWalletDB::TxnCommit()
849 return batch
.TxnCommit();
852 bool CWalletDB::TxnAbort()
854 return batch
.TxnAbort();
857 bool CWalletDB::ReadVersion(int& nVersion
)
859 return batch
.ReadVersion(nVersion
);
862 bool CWalletDB::WriteVersion(int nVersion
)
864 return batch
.WriteVersion(nVersion
);