@ -87,7 +87,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
return & ( it - > second ) ;
return & ( it - > second ) ;
}
}
CPubKey CWallet : : GenerateNewKey ( bool internal )
CPubKey CWallet : : GenerateNewKey ( CWalletDB & walletdb , bool internal )
{
{
AssertLockHeld ( cs_wallet ) ; // mapKeyMetadata
AssertLockHeld ( cs_wallet ) ; // mapKeyMetadata
bool fCompressed = CanSupportFeature ( FEATURE_COMPRPUBKEY ) ; // default to compressed public keys if we want 0.6.0 wallets
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
// use HD key derivation if HD was enabled during wallet creation
if ( IsHDEnabled ( ) ) {
if ( IsHDEnabled ( ) ) {
DeriveNewChildKey ( metadata , secret , ( CanSupportFeature ( FEATURE_HD_SPLIT ) ? internal : false ) ) ;
DeriveNewChildKey ( walletdb , metadata , secret , ( CanSupportFeature ( FEATURE_HD_SPLIT ) ? internal : false ) ) ;
} else {
} else {
secret . MakeNewKey ( fCompressed ) ;
secret . MakeNewKey ( fCompressed ) ;
}
}
// Compressed public keys were introduced in version 0.6.0
// Compressed public keys were introduced in version 0.6.0
if ( fCompressed )
if ( fCompressed ) {
SetMinVersion ( FEATURE_COMPRPUBKEY ) ;
SetMinVersion ( FEATURE_COMPRPUBKEY ) ;
}
CPubKey pubkey = secret . GetPubKey ( ) ;
CPubKey pubkey = secret . GetPubKey ( ) ;
assert ( secret . VerifyPubKey ( pubkey ) ) ;
assert ( secret . VerifyPubKey ( pubkey ) ) ;
@ -115,12 +116,13 @@ CPubKey CWallet::GenerateNewKey(bool internal)
mapKeyMetadata [ pubkey . GetID ( ) ] = metadata ;
mapKeyMetadata [ pubkey . GetID ( ) ] = metadata ;
UpdateTimeFirstKey ( nCreationTime ) ;
UpdateTimeFirstKey ( nCreationTime ) ;
if ( ! AddKeyPubKey ( secret , pubkey ) )
if ( ! AddKeyPubKeyWithDB ( walletdb , secret , pubkey ) ) {
throw std : : runtime_error ( std : : string ( __func__ ) + " : AddKey failed " ) ;
throw std : : runtime_error ( std : : string ( __func__ ) + " : AddKey failed " ) ;
}
return pubkey ;
return pubkey ;
}
}
void CWallet : : DeriveNewChildKey ( CKeyMetadata & metadata , CKey & secret , bool internal )
void CWallet : : DeriveNewChildKey ( CWalletDB & walletdb , C KeyMetadata & metadata , CKey & secret , bool internal )
{
{
// for now we use a fixed keypath scheme of m/0'/0'/k
// for now we use a fixed keypath scheme of m/0'/0'/k
CKey key ; //master key seed (256bit)
CKey key ; //master key seed (256bit)
@ -162,33 +164,52 @@ void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool inter
secret = childKey . key ;
secret = childKey . key ;
metadata . hdMasterKeyID = hdChain . masterKeyID ;
metadata . hdMasterKeyID = hdChain . masterKeyID ;
// update the chain model in the database
// 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 " ) ;
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
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 ;
return false ;
}
if ( needsDB ) pwalletdbEncryption = NULL ;
// check if we need to remove from watch-only
// check if we need to remove from watch-only
CScript script ;
CScript script ;
script = GetScriptForDestination ( pubkey . GetID ( ) ) ;
script = GetScriptForDestination ( pubkey . GetID ( ) ) ;
if ( HaveWatchOnly ( script ) )
if ( HaveWatchOnly ( script ) ) {
RemoveWatchOnly ( script ) ;
RemoveWatchOnly ( script ) ;
}
script = GetScriptForRawPubKey ( pubkey ) ;
script = GetScriptForRawPubKey ( pubkey ) ;
if ( HaveWatchOnly ( script ) )
if ( HaveWatchOnly ( script ) ) {
RemoveWatchOnly ( script ) ;
RemoveWatchOnly ( script ) ;
}
if ( ! IsCrypted ( ) ) {
if ( ! IsCrypted ( ) ) {
return CWalletDB ( * dbw ) . WriteKey ( pubkey ,
return walletdb . WriteKey ( pubkey ,
secret . GetPrivKey ( ) ,
secret . GetPrivKey ( ) ,
mapKeyMetadata [ pubkey . GetID ( ) ] ) ;
mapKeyMetadata [ pubkey . GetID ( ) ] ) ;
}
}
return true ;
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 ,
bool CWallet : : AddCryptedKey ( const CPubKey & vchPubKey ,
const std : : vector < unsigned char > & vchCryptedSecret )
const std : : vector < unsigned char > & vchCryptedSecret )
{
{
@ -3197,15 +3218,18 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
nEnd = std : : max ( nEnd , * ( setExternalKeyPool . rbegin ( ) ) + 1 ) ;
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 " ) ;
throw std : : runtime_error ( std : : string ( __func__ ) + " : writing generated key failed " ) ;
}
if ( internal ) {
if ( internal ) {
setInternalKeyPool . insert ( nEnd ) ;
setInternalKeyPool . insert ( nEnd ) ;
} else {
} else {
setExternalKeyPool . insert ( nEnd ) ;
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 ;
return true ;
@ -3280,7 +3304,8 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
if ( nIndex = = - 1 )
if ( nIndex = = - 1 )
{
{
if ( IsLocked ( ) ) return false ;
if ( IsLocked ( ) ) return false ;
result = GenerateNewKey ( internal ) ;
CWalletDB walletdb ( * dbw ) ;
result = GenerateNewKey ( walletdb , internal ) ;
return true ;
return true ;
}
}
KeepKey ( nIndex ) ;
KeepKey ( nIndex ) ;