mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Merge #10831: Batch flushing operations to the walletdb during top up and increase keypool size.
b0e8e2d
Print one log message per keypool top-up, not one per key. (Gregory Maxwell)41dc163
Increase wallet default keypool size to 1000. (Gregory Maxwell)30d8f3a
Pushdown walletdb though CWallet::AddKeyPubKey to avoid flushes. (Gregory Maxwell)3a53f19
Pushdown walletdb object through GenerateNewKey/DeriveNewChildKey. (Gregory Maxwell) Pull request description: This carries the walletdb object from top-up through GenerateNewKey/DeriveNewChildKey/CWallet::AddKeyPubKey, which allows us to avoid the flush on destruction until the top up finishes instead of flushing the wallet for every key. This speeds up adding keys by well over 10x on my laptop (actually something like 17x), I wouldn't be surprised if it were an even bigger speedup on spinning rust. Then it increases the keypool size to 1000. I would have preferred to use 10,000 but in the case where the user creates a new wallet and then turns on encryption it seems kind of dumb to have >400KB of marked-used born unencrypted keys just laying around. (Thanks to Matt for cluesticking me on how to bypass the crypter spaghetti) Tree-SHA512: 868303de38fce4c3f67d7fe133f765f15435c94b39d252d7450b5fee5c607a3cc2f5e531861a69d8c8877bf130e0ff4c539f97500a6bc0ff6d67e4a42c9385c7
This commit is contained in:
commit
0b019357ff
@ -87,7 +87,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
return &(it->second);
|
||||
}
|
||||
|
||||
CPubKey CWallet::GenerateNewKey(bool internal)
|
||||
CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
|
||||
@ -100,14 +100,15 @@ CPubKey CWallet::GenerateNewKey(bool internal)
|
||||
|
||||
// use HD key derivation if HD was enabled during wallet creation
|
||||
if (IsHDEnabled()) {
|
||||
DeriveNewChildKey(metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
|
||||
DeriveNewChildKey(walletdb, metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
|
||||
} else {
|
||||
secret.MakeNewKey(fCompressed);
|
||||
}
|
||||
|
||||
// Compressed public keys were introduced in version 0.6.0
|
||||
if (fCompressed)
|
||||
if (fCompressed) {
|
||||
SetMinVersion(FEATURE_COMPRPUBKEY);
|
||||
}
|
||||
|
||||
CPubKey pubkey = secret.GetPubKey();
|
||||
assert(secret.VerifyPubKey(pubkey));
|
||||
@ -115,12 +116,13 @@ CPubKey CWallet::GenerateNewKey(bool internal)
|
||||
mapKeyMetadata[pubkey.GetID()] = metadata;
|
||||
UpdateTimeFirstKey(nCreationTime);
|
||||
|
||||
if (!AddKeyPubKey(secret, pubkey))
|
||||
if (!AddKeyPubKeyWithDB(walletdb, secret, pubkey)) {
|
||||
throw std::runtime_error(std::string(__func__) + ": AddKey failed");
|
||||
}
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool internal)
|
||||
void CWallet::DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata& metadata, CKey& secret, bool internal)
|
||||
{
|
||||
// for now we use a fixed keypath scheme of m/0'/0'/k
|
||||
CKey key; //master key seed (256bit)
|
||||
@ -162,33 +164,52 @@ void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool inter
|
||||
secret = childKey.key;
|
||||
metadata.hdMasterKeyID = hdChain.masterKeyID;
|
||||
// update the chain model in the database
|
||||
if (!CWalletDB(*dbw).WriteHDChain(hdChain))
|
||||
if (!walletdb.WriteHDChain(hdChain))
|
||||
throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed");
|
||||
}
|
||||
|
||||
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
||||
bool CWallet::AddKeyPubKeyWithDB(CWalletDB &walletdb, const CKey& secret, const CPubKey &pubkey)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
|
||||
|
||||
// CCryptoKeyStore has no concept of wallet databases, but calls AddCryptedKey
|
||||
// which is overridden below. To avoid flushes, the database handle is
|
||||
// tunneled through to it.
|
||||
bool needsDB = !pwalletdbEncryption;
|
||||
if (needsDB) {
|
||||
pwalletdbEncryption = &walletdb;
|
||||
}
|
||||
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) {
|
||||
if (needsDB) pwalletdbEncryption = NULL;
|
||||
return false;
|
||||
}
|
||||
if (needsDB) pwalletdbEncryption = NULL;
|
||||
|
||||
// check if we need to remove from watch-only
|
||||
CScript script;
|
||||
script = GetScriptForDestination(pubkey.GetID());
|
||||
if (HaveWatchOnly(script))
|
||||
if (HaveWatchOnly(script)) {
|
||||
RemoveWatchOnly(script);
|
||||
}
|
||||
script = GetScriptForRawPubKey(pubkey);
|
||||
if (HaveWatchOnly(script))
|
||||
if (HaveWatchOnly(script)) {
|
||||
RemoveWatchOnly(script);
|
||||
}
|
||||
|
||||
if (!IsCrypted()) {
|
||||
return CWalletDB(*dbw).WriteKey(pubkey,
|
||||
return walletdb.WriteKey(pubkey,
|
||||
secret.GetPrivKey(),
|
||||
mapKeyMetadata[pubkey.GetID()]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
||||
{
|
||||
CWalletDB walletdb(*dbw);
|
||||
return CWallet::AddKeyPubKeyWithDB(walletdb, secret, pubkey);
|
||||
}
|
||||
|
||||
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
|
||||
const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
@ -3197,15 +3218,18 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
|
||||
nEnd = std::max(nEnd, *(setExternalKeyPool.rbegin()) + 1);
|
||||
}
|
||||
|
||||
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(internal), internal)))
|
||||
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(walletdb, internal), internal))) {
|
||||
throw std::runtime_error(std::string(__func__) + ": writing generated key failed");
|
||||
}
|
||||
|
||||
if (internal) {
|
||||
setInternalKeyPool.insert(nEnd);
|
||||
} else {
|
||||
setExternalKeyPool.insert(nEnd);
|
||||
}
|
||||
LogPrintf("keypool added key %d, size=%u (%u internal), new key is %s\n", nEnd, setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size(), internal ? "internal" : "external");
|
||||
}
|
||||
if (missingInternal + missingExternal > 0) {
|
||||
LogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -3280,7 +3304,8 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
|
||||
if (nIndex == -1)
|
||||
{
|
||||
if (IsLocked()) return false;
|
||||
result = GenerateNewKey(internal);
|
||||
CWalletDB walletdb(*dbw);
|
||||
result = GenerateNewKey(walletdb, internal);
|
||||
return true;
|
||||
}
|
||||
KeepKey(nIndex);
|
||||
|
@ -40,7 +40,7 @@ extern unsigned int nTxConfirmTarget;
|
||||
extern bool bSpendZeroConfChange;
|
||||
extern bool fWalletRbf;
|
||||
|
||||
static const unsigned int DEFAULT_KEYPOOL_SIZE = 100;
|
||||
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
|
||||
//! -paytxfee default
|
||||
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
|
||||
//! -fallbackfee default
|
||||
@ -697,7 +697,7 @@ private:
|
||||
CHDChain hdChain;
|
||||
|
||||
/* HD derive new child key (on internal or external chain) */
|
||||
void DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool internal = false);
|
||||
void DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata& metadata, CKey& secret, bool internal = false);
|
||||
|
||||
std::set<int64_t> setInternalKeyPool;
|
||||
std::set<int64_t> setExternalKeyPool;
|
||||
@ -866,9 +866,10 @@ public:
|
||||
* keystore implementation
|
||||
* Generate a new key
|
||||
*/
|
||||
CPubKey GenerateNewKey(bool internal = false);
|
||||
CPubKey GenerateNewKey(CWalletDB& walletdb, bool internal = false);
|
||||
//! Adds a key to the store, and saves it to disk.
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
|
||||
bool AddKeyPubKeyWithDB(CWalletDB &walletdb,const CKey& key, const CPubKey &pubkey);
|
||||
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
|
||||
//! Load metadata (used by LoadWallet)
|
||||
|
Loading…
Reference in New Issue
Block a user