| 181 | } |
| 182 | |
| 183 | void CWallet::DeriveNewChildKey(const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool internal) |
| 184 | { |
| 185 | CHDChain hdChainTmp; |
| 186 | if (!GetHDChain(hdChainTmp)) { |
| 187 | throw std::runtime_error(std::string(__func__) + ": GetHDChain failed"); |
| 188 | } |
| 189 | |
| 190 | if (!DecryptHDChain(hdChainTmp)) |
| 191 | throw std::runtime_error(std::string(__func__) + ": DecryptHDChainSeed failed"); |
| 192 | // make sure seed matches this chain |
| 193 | if (hdChainTmp.GetID() != hdChainTmp.GetSeedHash()) |
| 194 | throw std::runtime_error(std::string(__func__) + ": Wrong HD chain!"); |
| 195 | |
| 196 | CHDAccount acc; |
| 197 | if (!hdChainTmp.GetAccount(nAccountIndex, acc)) |
| 198 | throw std::runtime_error(std::string(__func__) + ": Wrong HD account!"); |
| 199 | |
| 200 | // derive child key at next index, skip keys already known to the wallet |
| 201 | CExtKey childKey; |
| 202 | uint32_t nChildIndex = internal ? acc.nInternalChainCounter : acc.nExternalChainCounter; |
| 203 | do { |
| 204 | hdChainTmp.DeriveChildExtKey(nAccountIndex, internal, nChildIndex, childKey); |
| 205 | // increment childkey index |
| 206 | nChildIndex++; |
| 207 | } while (HaveKey(childKey.key.GetPubKey().GetID())); |
| 208 | secretRet = childKey.key; |
| 209 | |
| 210 | CPubKey pubkey = secretRet.GetPubKey(); |
| 211 | assert(secretRet.VerifyPubKey(pubkey)); |
| 212 | |
| 213 | // store metadata |
| 214 | mapKeyMetadata[pubkey.GetID()] = metadata; |
| 215 | if (!nTimeFirstKey || metadata.nCreateTime < nTimeFirstKey) |
| 216 | nTimeFirstKey = metadata.nCreateTime; |
| 217 | |
| 218 | // update the chain model in the database |
| 219 | CHDChain hdChainCurrent; |
| 220 | GetHDChain(hdChainCurrent); |
| 221 | |
| 222 | if (internal) { |
| 223 | acc.nInternalChainCounter = nChildIndex; |
| 224 | } |
| 225 | else { |
| 226 | acc.nExternalChainCounter = nChildIndex; |
| 227 | } |
| 228 | |
| 229 | if (!hdChainCurrent.SetAccount(nAccountIndex, acc)) |
| 230 | throw std::runtime_error(std::string(__func__) + ": SetAccount failed"); |
| 231 | |
| 232 | if (IsCrypted()) { |
| 233 | if (!SetCryptedHDChain(hdChainCurrent, false)) |
| 234 | throw std::runtime_error(std::string(__func__) + ": SetCryptedHDChain failed"); |
| 235 | } |
| 236 | else { |
| 237 | if (!SetHDChain(hdChainCurrent, false)) |
| 238 | throw std::runtime_error(std::string(__func__) + ": SetHDChain failed"); |
| 239 | } |
| 240 |
nothing calls this directly
no test coverage detected