| 323 | } |
| 324 | |
| 325 | bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc, std::vector<unsigned char>* tweak) const { |
| 326 | assert(IsValid()); |
| 327 | assert(IsCompressed()); |
| 328 | std::vector<unsigned char, secure_allocator<unsigned char>> vout(64); |
| 329 | if ((nChild >> 31) == 0) { |
| 330 | CPubKey pubkey = GetPubKey(); |
| 331 | assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); |
| 332 | BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data()); |
| 333 | } else { |
| 334 | assert(size() == 32); |
| 335 | BIP32Hash(cc, nChild, 0, begin(), vout.data()); |
| 336 | } |
| 337 | if (tweak) { |
| 338 | tweak->clear(); |
| 339 | *tweak = std::vector<unsigned char>(vout.data(), vout.data()+32); |
| 340 | } |
| 341 | memcpy(ccChild.begin(), vout.data()+32, 32); |
| 342 | memcpy((unsigned char*)keyChild.begin(), begin(), 32); |
| 343 | bool ret = secp256k1_ec_seckey_tweak_add(secp256k1_context_sign, (unsigned char*)keyChild.begin(), vout.data()); |
| 344 | keyChild.fCompressed = true; |
| 345 | keyChild.fValid = ret; |
| 346 | return ret; |
| 347 | } |
| 348 | |
| 349 | bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const { |
| 350 | out.nDepth = nDepth + 1; |