So I've managed to obtain the correct private key for the address and have transferred the funds to a more modern wallet. Doing so was straightforward:
1) "getaddressinfo" on the address provided a json record for the address including a "parent_desc" field.
2) "listdescriptors true" provided the private descriptors.
3) I looked up the private descriptor based on the bracketed identifier in "parent_desc", the base58 identifier next to it was the private key (e.g. "combo([identifier]private_key)")
I was able to paste this key into Electrum, create a wallet and transfer the funds.
I don't expect this exact process will necessarily work with all key types, it looks like modern keys might be a little more complicated.
Also, by way of full disclosure, I should point out that I did all this with a slightly modified bitcoin core daemon. When I initially tried to migrate the wallet, I was getting an error because the wallet lacked a "best block locator record." This is an issue that was ostensibly fixed (see
https://github.com/bitcoin/bitcoin/pull/34198) but seemed to still be causing problems during the export of the migrated wallet. The following patch (against commit ca7162cde58e69214a3309c17fac6d666b5f055a) fixed it for me locally:
diff --git a/src/wallet/export.cpp b/src/wallet/export.cpp
index 9f9a9486db..e23cb93c11 100644
--- a/src/wallet/export.cpp
+++ b/src/wallet/export.cpp
@@ -149,13 +149,12 @@ util::Result<std::string> ExportWatchOnlyWallet(const CWallet& wallet, const fs:
CBlockLocator best_block_locator;
{
WalletBatch local_wallet_batch(wallet.GetDatabase());
- if (!local_wallet_batch.ReadBestBlock(best_block_locator)) {
- return util::Error{_("Error: Unable to read wallet's best block locator record")};
+ if (local_wallet_batch.ReadBestBlock(best_block_locator)) {
+ if (!watchonly_batch.WriteBestBlock(best_block_locator)) {
+ return util::Error{_("Error: Unable to write watchonly wallet best block locator record")};
+ }
}
}
- if (!watchonly_batch.WriteBestBlock(best_block_locator)) {
- return util::Error{_("Error: Unable to write watchonly wallet best block locator record")};
- }
// Copy the transactions
for (const auto& [txid, wtx] : wallet.mapWallet) {
This may have only been a problem because my node didn't have a full copy of the blockchain (perhaps this record gets filled in during migration for a system that does). If anyone thinks it's worth reporting, I'll open an issue with the core devs.
Thanks again, all, for your help!