Skip to content

Commit c9af030

Browse files
committed
rpc: Add getxpub command
1 parent aee80e5 commit c9af030

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

src/wallet/keyman.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ std::optional<CExtKey> KeyManager::GetActiveHDKey() const
7676
return master_key;
7777
}
7878

79+
std::optional<CExtPubKey> KeyManager::GetActiveHDPubKey() const
80+
{
81+
if (!m_active_xpub.pubkey.IsValid()) {
82+
return std::nullopt;
83+
}
84+
return m_active_xpub;
85+
}
86+
7987
bool KeyManager::AddKeyInner(WalletBatch& batch, const CKey& key, const CPubKey& pubkey)
8088
{
8189
AssertLockHeld(cs_keyman);

src/wallet/keyman.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class KeyManager
5050
bool AddHDKey(WalletBatch& batch, const CExtKey& extkey, const CExtPubKey& extpub);
5151

5252
std::optional<CExtKey> GetActiveHDKey() const EXCLUSIVE_LOCKS_REQUIRED(cs_keyman);
53+
std::optional<CExtPubKey> GetActiveHDPubKey() const EXCLUSIVE_LOCKS_REQUIRED(cs_keyman);
5354
std::map<CKeyID, CKey> GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_keyman);
5455
std::optional<std::pair<CPubKey, std::vector<unsigned char>>> GetCryptedKey(const CKeyID& id) const EXCLUSIVE_LOCKS_REQUIRED(cs_keyman);
5556

src/wallet/rpc/addresses.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,4 +786,48 @@ RPCHelpMan walletdisplayaddress()
786786
};
787787
}
788788
#endif // ENABLE_EXTERNAL_SIGNER
789+
790+
RPCHelpMan getxpub()
791+
{
792+
return RPCHelpMan{"getxpub",
793+
"Returns the xpub most recently used to generate descriptors for this descriptor wallet. "
794+
"Not entirely useful right now as it returns the xpub of the root, and there are "
795+
"hardened derivation steps involved in normal key derivation.\n",
796+
{},
797+
RPCResult{
798+
RPCResult::Type::OBJ, "", "",
799+
{
800+
{
801+
{RPCResult::Type::STR, "xpub", "The xpub"},
802+
}},
803+
},
804+
RPCExamples{
805+
HelpExampleCli("getxpub", "")
806+
+ HelpExampleRpc("getxpub", "")
807+
},
808+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
809+
{
810+
const std::shared_ptr<CWallet> pwallet = GetWalletForJSONRPCRequest(request);
811+
if (!pwallet) return NullUniValue;
812+
813+
if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
814+
throw JSONRPCError(RPC_WALLET_ERROR, "getxpub is not available for non-descriptor wallets");
815+
}
816+
817+
const KeyManager& keyman = pwallet->GetKeyManager();
818+
LOCK2(pwallet->cs_wallet, keyman.cs_keyman);
819+
820+
std::optional<CExtPubKey> extpub = keyman.GetActiveHDPubKey();
821+
if (extpub == std::nullopt) {
822+
throw JSONRPCError(RPC_WALLET_ERROR, "This wallet does not have an active xpub");
823+
}
824+
std::string xpub = EncodeExtPubKey(*extpub);
825+
826+
UniValue obj(UniValue::VOBJ);
827+
obj.pushKV("xpub", xpub);
828+
829+
return obj;
830+
},
831+
};
832+
}
789833
} // namespace wallet

src/wallet/rpc/wallet.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ RPCHelpMan listlabels();
768768
#ifdef ENABLE_EXTERNAL_SIGNER
769769
RPCHelpMan walletdisplayaddress();
770770
#endif // ENABLE_EXTERNAL_SIGNER
771+
RPCHelpMan getxpub();
771772

772773
// backup
773774
RPCHelpMan dumpprivkey();
@@ -852,6 +853,7 @@ Span<const CRPCCommand> GetWalletRPCCommands()
852853
{"wallet", &getunconfirmedbalance},
853854
{"wallet", &getbalances},
854855
{"wallet", &getwalletinfo},
856+
{"wallet", &getxpub},
855857
{"wallet", &importaddress},
856858
{"wallet", &importdescriptors},
857859
{"wallet", &importmulti},

0 commit comments

Comments
 (0)