mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-08-04 14:04:49 +02:00
Merge branch 'importfromcoldcard' into codex32-27+knots
This commit is contained in:
commit
dfb230e19f
@ -50,6 +50,7 @@ static void SetupWalletToolArgs(ArgsManager& argsman)
|
|||||||
argsman.AddCommand("salvage", "Attempt to recover private keys from a corrupt wallet. Warning: 'salvage' is experimental.");
|
argsman.AddCommand("salvage", "Attempt to recover private keys from a corrupt wallet. Warning: 'salvage' is experimental.");
|
||||||
argsman.AddCommand("dump", "Print out all of the wallet key-value records");
|
argsman.AddCommand("dump", "Print out all of the wallet key-value records");
|
||||||
argsman.AddCommand("createfromdump", "Create new wallet file from dumped records");
|
argsman.AddCommand("createfromdump", "Create new wallet file from dumped records");
|
||||||
|
argsman.AddCommand("importfromcoldcard", "Create new wallet file and import descriptors from Coldcard wallet");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<int> WalletAppInit(ArgsManager& args, int argc, char* argv[])
|
static std::optional<int> WalletAppInit(ArgsManager& args, int argc, char* argv[])
|
||||||
|
@ -1486,7 +1486,7 @@ RPCHelpMan importmulti()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
||||||
{
|
{
|
||||||
UniValue warnings(UniValue::VARR);
|
UniValue warnings(UniValue::VARR);
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include <wallet/wallettool.h>
|
#include <wallet/wallettool.h>
|
||||||
|
|
||||||
#include <common/args.h>
|
#include <common/args.h>
|
||||||
|
#include <tinyformat.h>
|
||||||
|
#include <univalue.h>
|
||||||
#include <util/fs.h>
|
#include <util/fs.h>
|
||||||
#include <util/translation.h>
|
#include <util/translation.h>
|
||||||
#include <wallet/dump.h>
|
#include <wallet/dump.h>
|
||||||
@ -16,7 +18,15 @@
|
|||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
#include <wallet/walletutil.h>
|
#include <wallet/walletutil.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace wallet {
|
namespace wallet {
|
||||||
|
|
||||||
|
UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, const int64_t timestamp)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
||||||
|
|
||||||
namespace WalletTool {
|
namespace WalletTool {
|
||||||
|
|
||||||
// The standard wallet deleter function blocks on the validation interface
|
// The standard wallet deleter function blocks on the validation interface
|
||||||
@ -36,6 +46,10 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag
|
|||||||
wallet_instance->SetMinVersion(FEATURE_LATEST);
|
wallet_instance->SetMinVersion(FEATURE_LATEST);
|
||||||
wallet_instance->InitWalletFlags(wallet_creation_flags);
|
wallet_instance->InitWalletFlags(wallet_creation_flags);
|
||||||
|
|
||||||
|
if (wallet_instance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||||
auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
|
auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
|
||||||
spk_man->SetupGeneration(false);
|
spk_man->SetupGeneration(false);
|
||||||
@ -112,14 +126,40 @@ static void WalletShowInfo(CWallet* wallet_instance)
|
|||||||
tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
|
tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ReadAndParseColdcardFile(const fs::path& path, UniValue& decriptors)
|
||||||
|
{
|
||||||
|
std::ifstream file;
|
||||||
|
file.open(path);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
tfm::format(std::cerr, "%s. Please check permissions.\n", fs::PathToString(path));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
if (line.substr(0, 22) == "importdescriptors \'[{\"") break;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
decriptors.clear();
|
||||||
|
if (!decriptors.read(line.substr(19, line.size() - 20))) {
|
||||||
|
tfm::format(std::cerr, "Unable to parse %s\n", fs::PathToString(path));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(decriptors.isArray());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
|
bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
|
||||||
{
|
{
|
||||||
if (args.IsArgSet("-format") && command != "createfromdump") {
|
if (args.IsArgSet("-format") && command != "createfromdump") {
|
||||||
tfm::format(std::cerr, "The -format option can only be used with the \"createfromdump\" command.\n");
|
tfm::format(std::cerr, "The -format option can only be used with the \"createfromdump\" command.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
|
if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump" && command != "importfromcoldcard") {
|
||||||
tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
|
tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\", \"createfromdump\" and \"importfromcoldcard\" commands.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (args.IsArgSet("-descriptors") && command != "create") {
|
if (args.IsArgSet("-descriptors") && command != "create") {
|
||||||
@ -219,6 +259,45 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
|
|||||||
tfm::format(std::cerr, "%s\n", error.original);
|
tfm::format(std::cerr, "%s\n", error.original);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
} else if (command == "importfromcoldcard") {
|
||||||
|
tfm::format(std::cerr, "WARNING: The \"importfromcoldcard\" command is experimental and will likely be removed or changed incompatibly in a future version.\n");
|
||||||
|
|
||||||
|
std::string filename = gArgs.GetArg("-dumpfile", "");
|
||||||
|
if (filename.empty()) {
|
||||||
|
tfm::format(std::cerr, "To use importfromcoldcard, -dumpfile=<filename> must be provided.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fs::path import_file_path{fs::absolute(fs::PathFromString(filename))};
|
||||||
|
if (!fs::exists(import_file_path)) {
|
||||||
|
tfm::format(std::cerr, "File %s does not exist.\n", fs::PathToString(import_file_path));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue descriptors;
|
||||||
|
if (!ReadAndParseColdcardFile(import_file_path, descriptors)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseOptions options;
|
||||||
|
options.require_create = true;
|
||||||
|
options.create_flags |= WALLET_FLAG_DESCRIPTORS;
|
||||||
|
options.create_flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
|
||||||
|
options.create_flags |= WALLET_FLAG_BLANK_WALLET;
|
||||||
|
options.require_format = DatabaseFormat::SQLITE;
|
||||||
|
std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
|
||||||
|
if (!wallet_instance) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCK(wallet_instance->cs_wallet);
|
||||||
|
for (const UniValue& descriptor : descriptors.getValues()) {
|
||||||
|
const UniValue result = ProcessDescriptorImport(*wallet_instance, descriptor, 0);
|
||||||
|
tfm::format(std::cerr, "%s\n", result.write(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletShowInfo(wallet_instance.get());
|
||||||
|
wallet_instance->Close();
|
||||||
} else {
|
} else {
|
||||||
tfm::format(std::cerr, "Invalid command: %s\n", command);
|
tfm::format(std::cerr, "Invalid command: %s\n", command);
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user