Skip to content

Commit 4e631bd

Browse files
committed
Add derivation helpers for peg-out wallet infrastructure
1 parent 1559cc9 commit 4e631bd

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
49134971
UniValue sendtomainchain(const JSONRPCRequest& request)
49144972
{
49154973
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);

0 commit comments

Comments
 (0)