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
& strAddress
)
46 return EraseIC(std::make_pair(std::string("purpose"), strAddress
));
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::ReadPool(int64_t nPool
, CKeyPool
& keypool
)
135 return batch
.Read(std::make_pair(std::string("pool"), nPool
), keypool
);
138 bool CWalletDB::WritePool(int64_t nPool
, const CKeyPool
& keypool
)
140 return WriteIC(std::make_pair(std::string("pool"), nPool
), keypool
);
143 bool CWalletDB::ErasePool(int64_t nPool
)
145 return EraseIC(std::make_pair(std::string("pool"), nPool
));
148 bool CWalletDB::WriteMinVersion(int nVersion
)
150 return WriteIC(std::string("minversion"), nVersion
);
153 bool CWalletDB::ReadAccount(const std::string
& strAccount
, CAccount
& account
)
156 return batch
.Read(std::make_pair(std::string("acc"), strAccount
), account
);
159 bool CWalletDB::WriteAccount(const std::string
& strAccount
, const CAccount
& account
)
161 return WriteIC(std::make_pair(std::string("acc"), strAccount
), account
);
164 bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum
, const CAccountingEntry
& acentry
)
166 return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry
.strAccount
, nAccEntryNum
)), acentry
);
169 CAmount
CWalletDB::GetAccountCreditDebit(const std::string
& strAccount
)
171 std::list
<CAccountingEntry
> entries
;
172 ListAccountCreditDebit(strAccount
, entries
);
174 CAmount nCreditDebit
= 0;
175 for (const CAccountingEntry
& entry
: entries
)
176 nCreditDebit
+= entry
.nCreditDebit
;
181 void CWalletDB::ListAccountCreditDebit(const std::string
& strAccount
, std::list
<CAccountingEntry
>& entries
)
183 bool fAllAccounts
= (strAccount
== "*");
185 Dbc
* pcursor
= batch
.GetCursor();
187 throw std::runtime_error(std::string(__func__
) + ": cannot create DB cursor");
188 bool setRange
= true;
192 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
194 ssKey
<< std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts
? std::string("") : strAccount
), uint64_t(0)));
195 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
196 int ret
= batch
.ReadAtCursor(pcursor
, ssKey
, ssValue
, setRange
);
198 if (ret
== DB_NOTFOUND
)
203 throw std::runtime_error(std::string(__func__
) + ": error scanning DB");
209 if (strType
!= "acentry")
211 CAccountingEntry acentry
;
212 ssKey
>> acentry
.strAccount
;
213 if (!fAllAccounts
&& acentry
.strAccount
!= strAccount
)
217 ssKey
>> acentry
.nEntryNo
;
218 entries
.push_back(acentry
);
224 class CWalletScanState
{
228 unsigned int nWatchKeys
;
229 unsigned int nKeyMeta
;
233 std::vector
<uint256
> vWalletUpgrade
;
236 nKeys
= nCKeys
= nWatchKeys
= nKeyMeta
= 0;
237 fIsEncrypted
= false;
238 fAnyUnordered
= false;
244 ReadKeyValue(CWallet
* pwallet
, CDataStream
& ssKey
, CDataStream
& ssValue
,
245 CWalletScanState
&wss
, std::string
& strType
, std::string
& strErr
)
249 // Taking advantage of the fact that pair serialization
250 // is just the two items serialized one after the other
252 if (strType
== "name")
254 std::string strAddress
;
256 ssValue
>> pwallet
->mapAddressBook
[DecodeDestination(strAddress
)].name
;
258 else if (strType
== "purpose")
260 std::string strAddress
;
262 ssValue
>> pwallet
->mapAddressBook
[DecodeDestination(strAddress
)].purpose
;
264 else if (strType
== "tx")
270 CValidationState state
;
271 if (!(CheckTransaction(*wtx
.tx
, state
) && (wtx
.GetHash() == hash
) && state
.IsValid()))
274 // Undo serialize changes in 31600
275 if (31404 <= wtx
.fTimeReceivedIsTxTime
&& wtx
.fTimeReceivedIsTxTime
<= 31703)
277 if (!ssValue
.empty())
281 ssValue
>> fTmp
>> fUnused
>> wtx
.strFromAccount
;
282 strErr
= strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s",
283 wtx
.fTimeReceivedIsTxTime
, fTmp
, wtx
.strFromAccount
, hash
.ToString());
284 wtx
.fTimeReceivedIsTxTime
= fTmp
;
288 strErr
= strprintf("LoadWallet() repairing tx ver=%d %s", wtx
.fTimeReceivedIsTxTime
, hash
.ToString());
289 wtx
.fTimeReceivedIsTxTime
= 0;
291 wss
.vWalletUpgrade
.push_back(hash
);
294 if (wtx
.nOrderPos
== -1)
295 wss
.fAnyUnordered
= true;
297 pwallet
->LoadToWallet(wtx
);
299 else if (strType
== "acentry")
301 std::string strAccount
;
305 if (nNumber
> pwallet
->nAccountingEntryNumber
) {
306 pwallet
->nAccountingEntryNumber
= nNumber
;
309 if (!wss
.fAnyUnordered
)
311 CAccountingEntry acentry
;
313 if (acentry
.nOrderPos
== -1)
314 wss
.fAnyUnordered
= true;
317 else if (strType
== "watchs")
325 pwallet
->LoadWatchOnly(script
);
327 else if (strType
== "key" || strType
== "wkey")
331 if (!vchPubKey
.IsValid())
333 strErr
= "Error reading wallet database: CPubKey corrupt";
340 if (strType
== "key")
347 pkey
= wkey
.vchPrivKey
;
350 // Old wallets store keys as "key" [pubkey] => [privkey]
351 // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
352 // using EC operations as a checksum.
353 // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
354 // remaining backwards-compatible.
361 bool fSkipCheck
= false;
365 // hash pubkey/privkey to accelerate wallet load
366 std::vector
<unsigned char> vchKey
;
367 vchKey
.reserve(vchPubKey
.size() + pkey
.size());
368 vchKey
.insert(vchKey
.end(), vchPubKey
.begin(), vchPubKey
.end());
369 vchKey
.insert(vchKey
.end(), pkey
.begin(), pkey
.end());
371 if (Hash(vchKey
.begin(), vchKey
.end()) != hash
)
373 strErr
= "Error reading wallet database: CPubKey/CPrivKey corrupt";
380 if (!key
.Load(pkey
, vchPubKey
, fSkipCheck
))
382 strErr
= "Error reading wallet database: CPrivKey corrupt";
385 if (!pwallet
->LoadKey(key
, vchPubKey
))
387 strErr
= "Error reading wallet database: LoadKey failed";
391 else if (strType
== "mkey")
395 CMasterKey kMasterKey
;
396 ssValue
>> kMasterKey
;
397 if(pwallet
->mapMasterKeys
.count(nID
) != 0)
399 strErr
= strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID
);
402 pwallet
->mapMasterKeys
[nID
] = kMasterKey
;
403 if (pwallet
->nMasterKeyMaxID
< nID
)
404 pwallet
->nMasterKeyMaxID
= nID
;
406 else if (strType
== "ckey")
410 if (!vchPubKey
.IsValid())
412 strErr
= "Error reading wallet database: CPubKey corrupt";
415 std::vector
<unsigned char> vchPrivKey
;
416 ssValue
>> vchPrivKey
;
419 if (!pwallet
->LoadCryptedKey(vchPubKey
, vchPrivKey
))
421 strErr
= "Error reading wallet database: LoadCryptedKey failed";
424 wss
.fIsEncrypted
= true;
426 else if (strType
== "keymeta" || strType
== "watchmeta")
428 CTxDestination keyID
;
429 if (strType
== "keymeta")
433 keyID
= vchPubKey
.GetID();
435 else if (strType
== "watchmeta")
439 keyID
= CScriptID(script
);
442 CKeyMetadata keyMeta
;
446 pwallet
->LoadKeyMetadata(keyID
, keyMeta
);
448 else if (strType
== "defaultkey")
450 // We don't want or need the default key, but if there is one set,
451 // we want to make sure that it is valid so that we can detect corruption
453 ssValue
>> vchPubKey
;
454 if (!vchPubKey
.IsValid()) {
455 strErr
= "Error reading wallet database: Default Key corrupt";
459 else if (strType
== "pool")
466 pwallet
->LoadKeyPool(nIndex
, keypool
);
468 else if (strType
== "version")
470 ssValue
>> wss
.nFileVersion
;
471 if (wss
.nFileVersion
== 10300)
472 wss
.nFileVersion
= 300;
474 else if (strType
== "cscript")
480 if (!pwallet
->LoadCScript(script
))
482 strErr
= "Error reading wallet database: LoadCScript failed";
486 else if (strType
== "orderposnext")
488 ssValue
>> pwallet
->nOrderPosNext
;
490 else if (strType
== "destdata")
492 std::string strAddress
, strKey
, strValue
;
496 if (!pwallet
->LoadDestData(DecodeDestination(strAddress
), strKey
, strValue
))
498 strErr
= "Error reading wallet database: LoadDestData failed";
502 else if (strType
== "hdchain")
506 if (!pwallet
->SetHDChain(chain
, true))
508 strErr
= "Error reading wallet database: SetHDChain failed";
519 bool CWalletDB::IsKeyType(const std::string
& strType
)
521 return (strType
== "key" || strType
== "wkey" ||
522 strType
== "mkey" || strType
== "ckey");
525 DBErrors
CWalletDB::LoadWallet(CWallet
* pwallet
)
527 CWalletScanState wss
;
528 bool fNoncriticalErrors
= false;
529 DBErrors result
= DB_LOAD_OK
;
531 LOCK(pwallet
->cs_wallet
);
534 if (batch
.Read((std::string
)"minversion", nMinVersion
))
536 if (nMinVersion
> CLIENT_VERSION
)
538 pwallet
->LoadMinVersion(nMinVersion
);
542 Dbc
* pcursor
= batch
.GetCursor();
545 LogPrintf("Error getting wallet database cursor\n");
552 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
553 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
554 int ret
= batch
.ReadAtCursor(pcursor
, ssKey
, ssValue
);
555 if (ret
== DB_NOTFOUND
)
559 LogPrintf("Error reading next record from wallet database\n");
563 // Try to be tolerant of single corrupt records:
564 std::string strType
, strErr
;
565 if (!ReadKeyValue(pwallet
, ssKey
, ssValue
, wss
, strType
, strErr
))
567 // losing keys is considered a catastrophic error, anything else
568 // we assume the user can live with:
569 if (IsKeyType(strType
) || strType
== "defaultkey")
573 // Leave other errors alone, if we try to fix them we might make things worse.
574 fNoncriticalErrors
= true; // ... but do warn the user there is something wrong.
576 // Rescan if there is a bad transaction record:
577 gArgs
.SoftSetBoolArg("-rescan", true);
581 LogPrintf("%s\n", strErr
);
585 catch (const boost::thread_interrupted
&) {
592 if (fNoncriticalErrors
&& result
== DB_LOAD_OK
)
593 result
= DB_NONCRITICAL_ERROR
;
595 // Any wallet corruption at all: skip any rewriting or
596 // upgrading, we don't want to make it worse.
597 if (result
!= DB_LOAD_OK
)
600 LogPrintf("nFileVersion = %d\n", wss
.nFileVersion
);
602 LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
603 wss
.nKeys
, wss
.nCKeys
, wss
.nKeyMeta
, wss
.nKeys
+ wss
.nCKeys
);
605 // nTimeFirstKey is only reliable if all keys have metadata
606 if ((wss
.nKeys
+ wss
.nCKeys
+ wss
.nWatchKeys
) != wss
.nKeyMeta
)
607 pwallet
->UpdateTimeFirstKey(1);
609 for (uint256 hash
: wss
.vWalletUpgrade
)
610 WriteTx(pwallet
->mapWallet
[hash
]);
612 // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
613 if (wss
.fIsEncrypted
&& (wss
.nFileVersion
== 40000 || wss
.nFileVersion
== 50000))
614 return DB_NEED_REWRITE
;
616 if (wss
.nFileVersion
< CLIENT_VERSION
) // Update
617 WriteVersion(CLIENT_VERSION
);
619 if (wss
.fAnyUnordered
)
620 result
= pwallet
->ReorderTransactions();
622 pwallet
->laccentries
.clear();
623 ListAccountCreditDebit("*", pwallet
->laccentries
);
624 for (CAccountingEntry
& entry
: pwallet
->laccentries
) {
625 pwallet
->wtxOrdered
.insert(make_pair(entry
.nOrderPos
, CWallet::TxPair(nullptr, &entry
)));
631 DBErrors
CWalletDB::FindWalletTx(std::vector
<uint256
>& vTxHash
, std::vector
<CWalletTx
>& vWtx
)
633 bool fNoncriticalErrors
= false;
634 DBErrors result
= DB_LOAD_OK
;
638 if (batch
.Read((std::string
)"minversion", nMinVersion
))
640 if (nMinVersion
> CLIENT_VERSION
)
645 Dbc
* pcursor
= batch
.GetCursor();
648 LogPrintf("Error getting wallet database cursor\n");
655 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
656 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
657 int ret
= batch
.ReadAtCursor(pcursor
, ssKey
, ssValue
);
658 if (ret
== DB_NOTFOUND
)
662 LogPrintf("Error reading next record from wallet database\n");
668 if (strType
== "tx") {
675 vTxHash
.push_back(hash
);
681 catch (const boost::thread_interrupted
&) {
688 if (fNoncriticalErrors
&& result
== DB_LOAD_OK
)
689 result
= DB_NONCRITICAL_ERROR
;
694 DBErrors
CWalletDB::ZapSelectTx(std::vector
<uint256
>& vTxHashIn
, std::vector
<uint256
>& vTxHashOut
)
696 // build list of wallet TXs and hashes
697 std::vector
<uint256
> vTxHash
;
698 std::vector
<CWalletTx
> vWtx
;
699 DBErrors err
= FindWalletTx(vTxHash
, vWtx
);
700 if (err
!= DB_LOAD_OK
) {
704 std::sort(vTxHash
.begin(), vTxHash
.end());
705 std::sort(vTxHashIn
.begin(), vTxHashIn
.end());
707 // erase each matching wallet TX
708 bool delerror
= false;
709 std::vector
<uint256
>::iterator it
= vTxHashIn
.begin();
710 for (uint256 hash
: vTxHash
) {
711 while (it
< vTxHashIn
.end() && (*it
) < hash
) {
714 if (it
== vTxHashIn
.end()) {
717 else if ((*it
) == hash
) {
719 LogPrint(BCLog::DB
, "Transaction was found for deletion but returned database error: %s\n", hash
.GetHex());
722 vTxHashOut
.push_back(hash
);
732 DBErrors
CWalletDB::ZapWalletTx(std::vector
<CWalletTx
>& vWtx
)
734 // build list of wallet TXs
735 std::vector
<uint256
> vTxHash
;
736 DBErrors err
= FindWalletTx(vTxHash
, vWtx
);
737 if (err
!= DB_LOAD_OK
)
740 // erase each wallet TX
741 for (uint256
& hash
: vTxHash
) {
749 void MaybeCompactWalletDB()
751 static std::atomic
<bool> fOneThread(false);
752 if (fOneThread
.exchange(true)) {
755 if (!gArgs
.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET
)) {
759 for (CWalletRef pwallet
: vpwallets
) {
760 CWalletDBWrapper
& dbh
= pwallet
->GetDBHandle();
762 unsigned int nUpdateCounter
= dbh
.nUpdateCounter
;
764 if (dbh
.nLastSeen
!= nUpdateCounter
) {
765 dbh
.nLastSeen
= nUpdateCounter
;
766 dbh
.nLastWalletUpdate
= GetTime();
769 if (dbh
.nLastFlushed
!= nUpdateCounter
&& GetTime() - dbh
.nLastWalletUpdate
>= 2) {
770 if (CDB::PeriodicFlush(dbh
)) {
771 dbh
.nLastFlushed
= nUpdateCounter
;
780 // Try to (very carefully!) recover wallet file if there is a problem.
782 bool CWalletDB::Recover(const std::string
& filename
, void *callbackDataIn
, bool (*recoverKVcallback
)(void* callbackData
, CDataStream ssKey
, CDataStream ssValue
), std::string
& out_backup_filename
)
784 return CDB::Recover(filename
, callbackDataIn
, recoverKVcallback
, out_backup_filename
);
787 bool CWalletDB::Recover(const std::string
& filename
, std::string
& out_backup_filename
)
789 // recover without a key filter callback
790 // results in recovering all record types
791 return CWalletDB::Recover(filename
, nullptr, nullptr, out_backup_filename
);
794 bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData
, CDataStream ssKey
, CDataStream ssValue
)
796 CWallet
*dummyWallet
= reinterpret_cast<CWallet
*>(callbackData
);
797 CWalletScanState dummyWss
;
798 std::string strType
, strErr
;
801 // Required in LoadKeyMetadata():
802 LOCK(dummyWallet
->cs_wallet
);
803 fReadOK
= ReadKeyValue(dummyWallet
, ssKey
, ssValue
,
804 dummyWss
, strType
, strErr
);
806 if (!IsKeyType(strType
) && strType
!= "hdchain")
810 LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType
, strErr
);
817 bool CWalletDB::VerifyEnvironment(const std::string
& walletFile
, const fs::path
& dataDir
, std::string
& errorStr
)
819 return CDB::VerifyEnvironment(walletFile
, dataDir
, errorStr
);
822 bool CWalletDB::VerifyDatabaseFile(const std::string
& walletFile
, const fs::path
& dataDir
, std::string
& warningStr
, std::string
& errorStr
)
824 return CDB::VerifyDatabaseFile(walletFile
, dataDir
, warningStr
, errorStr
, CWalletDB::Recover
);
827 bool CWalletDB::WriteDestData(const std::string
&address
, const std::string
&key
, const std::string
&value
)
829 return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address
, key
)), value
);
832 bool CWalletDB::EraseDestData(const std::string
&address
, const std::string
&key
)
834 return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address
, key
)));
838 bool CWalletDB::WriteHDChain(const CHDChain
& chain
)
840 return WriteIC(std::string("hdchain"), chain
);
843 bool CWalletDB::TxnBegin()
845 return batch
.TxnBegin();
848 bool CWalletDB::TxnCommit()
850 return batch
.TxnCommit();
853 bool CWalletDB::TxnAbort()
855 return batch
.TxnAbort();
858 bool CWalletDB::ReadVersion(int& nVersion
)
860 return batch
.ReadVersion(nVersion
);
863 bool CWalletDB::WriteVersion(int nVersion
)
865 return batch
.WriteVersion(nVersion
);