@@ -4910,6 +4910,64 @@ UniValue getpeginaddress(const JSONRPCRequest& request)
49104910 return fundinginfo;
49114911}
49124912
4913+ // ! Derive BIP32 tweak from master xpub to child pubkey.
4914+ bool DerivePubTweak (const std::vector<uint32_t >& vPath, const CPubKey& keyMaster, const ChainCode &ccMaster, std::vector<unsigned char >& tweakSum)
4915+ {
4916+ tweakSum.clear ();
4917+ tweakSum.resize (32 );
4918+ std::vector<unsigned char > tweak;
4919+ CPubKey keyParent = keyMaster;
4920+ CPubKey keyChild;
4921+ ChainCode ccChild;
4922+ ChainCode ccParent = ccMaster;
4923+ for (unsigned int i = 0 ; i < vPath.size (); i++) {
4924+ if ((vPath[i] >> 31 ) != 0 ) {
4925+ return false ;
4926+ }
4927+ keyParent.Derive (keyChild, ccChild, vPath[i], ccParent, &tweak);
4928+ assert (tweak.size () == 32 );
4929+ ccParent = ccChild;
4930+ keyParent = keyChild;
4931+ bool ret = secp256k1_ec_privkey_tweak_add (secp256k1_ctx, tweakSum.data (), tweak.data ());
4932+ if (!ret) {
4933+ return false ;
4934+ }
4935+ }
4936+ return true ;
4937+ }
4938+
4939+ CTxDestination DeriveBitcoinOfflineAddress (const CExtPubKey& xpub, const uint32_t counter)
4940+ {
4941+ std::vector<uint32_t > vPath;
4942+ vPath.push_back (0 );
4943+ vPath.push_back (counter);
4944+
4945+ std::vector<unsigned char > tweakSum;
4946+ if (!DerivePubTweak (vPath, xpub.pubkey , xpub.chaincode , tweakSum)) {
4947+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Could not derive the pubkey tweak for given counter and xpub." );
4948+ }
4949+
4950+ secp256k1_pubkey masterpub_secp;
4951+ int ret = secp256k1_ec_pubkey_parse (secp256k1_ctx, &masterpub_secp, xpub.pubkey .begin (), xpub.pubkey .size ());
4952+ if (ret != 1 ) {
4953+ throw JSONRPCError (RPC_WALLET_ERROR, " Master pubkey could not be parsed." );
4954+ }
4955+
4956+ ret = secp256k1_ec_pubkey_tweak_add (secp256k1_ctx, &masterpub_secp, tweakSum.data ());
4957+ assert (ret);
4958+
4959+ std::vector<unsigned char > btcpubkeybytes;
4960+ btcpubkeybytes.resize (33 );
4961+ size_t btclen = 33 ;
4962+ ret = secp256k1_ec_pubkey_serialize (secp256k1_ctx, &btcpubkeybytes[0 ], &btclen, &masterpub_secp, SECP256K1_EC_COMPRESSED);
4963+ assert (ret == 1 );
4964+ assert (btclen == 33 );
4965+ assert (btcpubkeybytes.size () == 33 );
4966+
4967+ CPubKey btcpub (btcpubkeybytes);
4968+ return CTxDestination (btcpub.GetID ());
4969+ }
4970+
49134971UniValue sendtomainchain (const JSONRPCRequest& request)
49144972{
49154973 std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest (request);
0 commit comments