@ -91,7 +91,48 @@ CPubKey CWallet::GenerateNewKey()
bool fCompressed = CanSupportFeature ( FEATURE_COMPRPUBKEY ) ; // default to compressed public keys if we want 0.6.0 wallets
CKey secret ;
secret . MakeNewKey ( fCompressed ) ;
// Create new metadata
int64_t nCreationTime = GetTime ( ) ;
CKeyMetadata metadata ( nCreationTime ) ;
// use HD key derivation if HD was enabled during wallet creation
if ( ! hdChain . masterKeyID . IsNull ( ) ) {
// for now we use a fixed keypath scheme of m/0'/0'/k
CKey key ; //master key seed (256bit)
CExtKey masterKey ; //hd master key
CExtKey accountKey ; //key at m/0'
CExtKey externalChainChildKey ; //key at m/0'/0'
CExtKey childKey ; //key at m/0'/0'/<n>'
// try to get the master key
if ( ! GetKey ( hdChain . masterKeyID , key ) )
throw std : : runtime_error ( " CWallet::GenerateNewKey(): Master key not found " ) ;
masterKey . SetMaster ( key . begin ( ) , key . size ( ) ) ;
// derive m/0'
// use hardened derivation (child keys > 0x80000000 are hardened after bip32)
masterKey . Derive ( accountKey , 0 | 0x80000000 ) ;
// derive m/0'/0'
accountKey . Derive ( externalChainChildKey , 0 | 0x80000000 ) ;
// derive child key at next index, skip keys already known to the wallet
do
{
externalChainChildKey . Derive ( childKey , hdChain . nExternalChainCounter | 0x80000000 ) ;
// increment childkey index
hdChain . nExternalChainCounter + + ;
} while ( HaveKey ( childKey . key . GetPubKey ( ) . GetID ( ) ) ) ;
secret = childKey . key ;
// update the chain model in the database
if ( ! CWalletDB ( strWalletFile ) . WriteHDChain ( hdChain ) )
throw std : : runtime_error ( " CWallet::GenerateNewKey(): Writing HD chain model failed " ) ;
} else {
secret . MakeNewKey ( fCompressed ) ;
}
// Compressed public keys were introduced in version 0.6.0
if ( fCompressed )
@ -100,9 +141,7 @@ CPubKey CWallet::GenerateNewKey()
CPubKey pubkey = secret . GetPubKey ( ) ;
assert ( secret . VerifyPubKey ( pubkey ) ) ;
// Create new metadata
int64_t nCreationTime = GetTime ( ) ;
mapKeyMetadata [ pubkey . GetID ( ) ] = CKeyMetadata ( nCreationTime ) ;
mapKeyMetadata [ pubkey . GetID ( ) ] = metadata ;
if ( ! nTimeFirstKey | | nCreationTime < nTimeFirstKey )
nTimeFirstKey = nCreationTime ;
@ -1049,6 +1088,37 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
return nChange ;
}
bool CWallet : : SetHDMasterKey ( const CKey & key )
{
LOCK ( cs_wallet ) ;
// store the key as normal "key"/"ckey" object
// in the database
// key metadata is not required
CPubKey pubkey = key . GetPubKey ( ) ;
if ( ! AddKeyPubKey ( key , pubkey ) )
throw std : : runtime_error ( " CWallet::GenerateNewKey(): AddKey failed " ) ;
// store the keyid (hash160) together with
// the child index counter in the database
// as a hdchain object
CHDChain newHdChain ;
newHdChain . masterKeyID = pubkey . GetID ( ) ;
SetHDChain ( newHdChain , false ) ;
return true ;
}
bool CWallet : : SetHDChain ( const CHDChain & chain , bool memonly )
{
LOCK ( cs_wallet ) ;
if ( ! memonly & & ! CWalletDB ( strWalletFile ) . WriteHDChain ( chain ) )
throw runtime_error ( " AddHDChain() : writing chain failed " ) ;
hdChain = chain ;
return true ;
}
int64_t CWalletTx : : GetTxTime ( ) const
{
int64_t n = nTimeSmart ;
@ -3058,6 +3128,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
strUsage + = HelpMessageOpt ( " -sendfreetransactions " , strprintf ( _ ( " Send transactions as zero-fee transactions if possible (default: %u) " ) , DEFAULT_SEND_FREE_TRANSACTIONS ) ) ;
strUsage + = HelpMessageOpt ( " -spendzeroconfchange " , strprintf ( _ ( " Spend unconfirmed change when sending transactions (default: %u) " ) , DEFAULT_SPEND_ZEROCONF_CHANGE ) ) ;
strUsage + = HelpMessageOpt ( " -txconfirmtarget=<n> " , strprintf ( _ ( " If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) " ) , DEFAULT_TX_CONFIRM_TARGET ) ) ;
strUsage + = HelpMessageOpt ( " -usehd " , _ ( " Use hierarchical deterministic key generation (HD) after bip32. Only has effect during wallet creation/first start " ) + " " + strprintf ( _ ( " (default: %u) " ) , DEFAULT_USE_HD_WALLET ) ) ;
strUsage + = HelpMessageOpt ( " -upgradewallet " , _ ( " Upgrade wallet to latest format on startup " ) ) ;
strUsage + = HelpMessageOpt ( " -wallet=<file> " , _ ( " Specify wallet file (within data directory) " ) + " " + strprintf ( _ ( " (default: %s) " ) , DEFAULT_WALLET_DAT ) ) ;
strUsage + = HelpMessageOpt ( " -walletbroadcast " , _ ( " Make the wallet broadcast transactions " ) + " " + strprintf ( _ ( " (default: %u) " ) , DEFAULT_WALLETBROADCAST ) ) ;
@ -3145,6 +3216,13 @@ bool CWallet::InitLoadWallet()
if ( fFirstRun )
{
// Create new keyUser and set as default key
if ( GetBoolArg ( " -usehd " , DEFAULT_USE_HD_WALLET ) ) {
// generate a new master key
CKey key ;
key . MakeNewKey ( true ) ;
if ( ! walletInstance - > SetHDMasterKey ( key ) )
throw std : : runtime_error ( " CWallet::GenerateNewKey(): Storing master key failed " ) ;
}
CPubKey newDefaultKey ;
if ( walletInstance - > GetKeyFromPool ( newDefaultKey ) ) {
walletInstance - > SetDefaultKey ( newDefaultKey ) ;