diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index c8cbfc8273b34..55c480fb408ea 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -43,7 +43,7 @@ static void SetupWalletToolArgs(ArgsManager& argsman) argsman.AddArg("-debug=", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-descriptors", "Create descriptors wallet. Only for 'create'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-blsct", "Create blsct wallet. Only for 'create'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-seed", "Seed used for the wallet creation. Only for 'create'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + argsman.AddArg("-seed", "Seed used for the wallet creation. Only for 'create'. Can be a master seed or an audit key.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-legacy", "Create legacy wallet. Only for 'create'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-format=", "The format of the wallet file to create. Either \"bdb\" or \"sqlite\". Only used with 'createfromdump'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); diff --git a/src/blsct/wallet/keyman.cpp b/src/blsct/wallet/keyman.cpp index 00cfc26ef1962..a2beb8436c5d9 100644 --- a/src/blsct/wallet/keyman.cpp +++ b/src/blsct/wallet/keyman.cpp @@ -267,19 +267,31 @@ bool KeyMan::SetupGeneration(const std::vector& seed, const SeedT return false; } - if (seed.size() != 32) { - SetHDSeed(GenerateNewSeed()); - } else { + if (seed.size() == 32) { if (type == IMPORT_MASTER_KEY) { MclScalar scalarSeed; scalarSeed.SetVch(seed); SetHDSeed(scalarSeed); - } else if (type == IMPORT_VIEW_KEY) { + } + } else if (seed.size() == 80) { + if (type == IMPORT_VIEW_KEY) { + std::vector viewVch(seed.begin(), seed.begin() + 32); + std::vector spendingVch(seed.begin() + 32, seed.end()); + MclScalar scalarView; - scalarView.SetVch(seed); - if (!AddViewKey(scalarView, viewKey.GetPublicKey())) + scalarView.SetVch(viewVch); + + MclG1Point pointSpending; + pointSpending.SetVch(spendingVch); + + if (!AddViewKey(scalarView, PrivateKey(scalarView).GetPublicKey())) throw std::runtime_error(std::string(__func__) + ": AddViewKey failed"); + + if (!AddSpendKey(pointSpending)) + throw std::runtime_error(std::string(__func__) + ": AddSpendKey failed"); } + } else { + SetHDSeed(GenerateNewSeed()); } if (!NewSubAddressPool() || !NewSubAddressPool(-1) || !NewSubAddressPool(-2)) { @@ -477,14 +489,12 @@ blsct::PrivateKey KeyMan::GetPrivateViewKey() const if (!fViewKeyDefined) throw std::runtime_error(strprintf("%s: the wallet has no view key available")); - auto viewId = m_hd_chain.view_id; - - PrivateKey ret; - - if (!GetKey(viewId, ret)) - throw std::runtime_error(strprintf("%s: could not access the private view key", __func__)); + return viewKey; +} - return ret; +blsct::PublicKey KeyMan::GetPublicSpendingKey() const +{ + return spendPublicKey; } blsct::PrivateKey KeyMan::GetSpendingKey() const diff --git a/src/blsct/wallet/keyman.h b/src/blsct/wallet/keyman.h index 897ea134409e0..4f04288d40721 100644 --- a/src/blsct/wallet/keyman.h +++ b/src/blsct/wallet/keyman.h @@ -137,6 +137,7 @@ class KeyMan : public Manager, public KeyRing CTxDestination GetDestination(const CTxOut& txout) const; blsct::PrivateKey GetMasterSeedKey() const; blsct::PrivateKey GetPrivateViewKey() const; + blsct::PublicKey GetPublicSpendingKey() const; blsct::PrivateKey GetSpendingKey() const; blsct::PrivateKey GetSpendingKeyForOutput(const CTxOut& out) const; blsct::PrivateKey GetSpendingKeyForOutput(const CTxOut& out, const CKeyID& id) const; diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp index 50d7cd622bbe9..2c008598b8f78 100644 --- a/src/wallet/rpc/backup.cpp +++ b/src/wallet/rpc/backup.cpp @@ -713,16 +713,16 @@ RPCHelpMan getblsctseed() } -RPCHelpMan getblsctviewkey() +RPCHelpMan getblsctauditkey() { return RPCHelpMan{ - "getblsctviewkey", - "\nDumps the BLSCT wallet private view key, which can be used to observe the wallet history without being able to spend the transactions.\n" + "getblsctauditkey", + "\nDumps the BLSCT wallet audit key, which can be used to observe the wallet history without being able to spend the transactions.\n" "Note: This command is only compatible with BLSCT wallets.\n", {}, RPCResult{ - RPCResult::Type::STR, "viewkey", "The BLSCT wallet private view key"}, - RPCExamples{HelpExampleCli("getblsctviewkey", "") + HelpExampleRpc("getblsctviewkey", "")}, + RPCResult::Type::STR, "auditkey", "The BLSCT wallet audit key"}, + RPCExamples{HelpExampleCli("getblsctauditkey", "") + HelpExampleRpc("getblsctauditkey", "")}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { const std::shared_ptr pwallet = GetWalletForJSONRPCRequest(request); if (!pwallet) return UniValue::VNULL; @@ -730,9 +730,8 @@ RPCHelpMan getblsctviewkey() const CWallet& wallet = *pwallet; const blsct::KeyMan& blsct_km = EnsureConstBlsctKeyMan(wallet); - auto seed = blsct_km.GetPrivateViewKey(); - - return seed.GetScalar().GetString(); + return strprintf("%s%s", blsct_km.GetPrivateViewKey().GetScalar().GetString(), HexStr(blsct_km.GetPublicSpendingKey().GetVch())); + ; }, }; } diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index f1639b6bbee55..96edc88c06548 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -354,8 +354,7 @@ static RPCHelpMan createwallet() {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."}, {"external_signer", RPCArg::Type::BOOL, RPCArg::Default{false}, "Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true."}, {"blsct", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a wallet with BLSCT keys."}, - {"seed", RPCArg::Type::STR_HEX, RPCArg::Default{""}, "Create the wallet from the specified seed."}, - {"viewkey", RPCArg::Type::STR_HEX, RPCArg::Default{""}, "Create the wallet from the specified view key."}, + {"seed", RPCArg::Type::STR_HEX, RPCArg::Default{""}, "Create the wallet from the specified seed (can be a master seed or an audit key)."}, }, RPCResult{ RPCResult::Type::OBJ, "", "", { @@ -419,10 +418,14 @@ static RPCHelpMan createwallet() blsct::SeedType type = blsct::IMPORT_MASTER_KEY; if (!request.params[9].isNull() && request.params[9].isStr()) { seed = ParseHex(request.params[9].get_str()); - } else if (!request.params[10].isNull() && request.params[10].isStr()) { + } + + if (seed.size() == 160) { seed = ParseHex(request.params[10].get_str()); type = blsct::IMPORT_VIEW_KEY; flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS; + } else if (seed.size() != 64) { + throw JSONRPCError(RPC_WALLET_ERROR, "Seed must be 64 (master) or 160 (view) characters long"); } DatabaseOptions options; @@ -841,7 +844,7 @@ RPCHelpMan walletdisplayaddress(); // backup RPCHelpMan getblsctseed(); -RPCHelpMan getblsctviewkey(); +RPCHelpMan getblsctauditkey(); RPCHelpMan dumpprivkey(); RPCHelpMan importprivkey(); RPCHelpMan importaddress(); @@ -921,7 +924,7 @@ Span GetWalletRPCCommands() {"wallet", &getaddressinfo}, {"wallet", &getbalance}, {"wallet", &getblsctseed}, - {"wallet", &getblsctviewkey}, + {"wallet", &getblsctauditkey}, {"wallet", &getnewaddress}, {"wallet", &getrawchangeaddress}, {"wallet", &getreceivedbyaddress}, diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index 6710030cc8c5d..042fe991b9023 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -36,14 +36,14 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag wallet_instance->SetMinVersion(FEATURE_LATEST); wallet_instance->InitWalletFlags(wallet_creation_flags); - if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { - auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan(); - spk_man->SetupGeneration(false); + if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_BLSCT)) { + if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { + auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan(); + spk_man->SetupGeneration(false); + } else { + wallet_instance->SetupDescriptorScriptPubKeyMans(); + } } else { - wallet_instance->SetupDescriptorScriptPubKeyMans(); - } - - { auto blsct_man = wallet_instance->GetOrCreateBLSCTKeyMan(); if (blsct_man) { @@ -143,10 +143,6 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command) tfm::format(std::cerr, "The -seed option can only be used with the 'create' command.\n"); return false; } - if (args.IsArgSet("-viewkey") && command != "create") { - tfm::format(std::cerr, "The -viewkey option can only be used with the 'create' command.\n"); - return false; - } if (command == "create" && !args.IsArgSet("-wallet")) { tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n"); return false; @@ -183,14 +179,12 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command) } - std::string seed; + std::string seed = args.GetArg("-seed", ""); blsct::SeedType type; - if (args.IsArgSet("-seed")) { - seed = args.GetArg("-seed", ""); + if (seed.size() == 64) { type = blsct::IMPORT_MASTER_KEY; - } else if (args.IsArgSet("-viewkey")) { - seed = args.GetArg("-seed", ""); + } else if (seed.size() == 64 + 96) { type = blsct::IMPORT_VIEW_KEY; options.create_flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS; }