This refactor introduces quite a few string copy operations, where previously references were passed. I think this can be quite easily avoided with the below patch. There are other callsites of LabelFromValue that would benefit from just changing their type to const std::string&, but to keep LoC change minimal I've not changed them in this patch.
<details>
<summary>git diff on ba1e78a2d58059f439f17e821eb2d1bab4db86cb</summary>
diff --git a/src/wallet/rpc/addresses.cpp b/src/wallet/rpc/addresses.cpp
index e819c09c5..5d04d3113 100644
--- a/src/wallet/rpc/addresses.cpp
+++ b/src/wallet/rpc/addresses.cpp
@@ -43,7 +43,7 @@ RPCHelpMan getnewaddress()
}
// Parse the label first so we don't generate a key if there's an error
- std::string label{LabelFromValue(request.params[0])};
+ const std::string& label{LabelFromValue(request.params[0])};
OutputType output_type = pwallet->m_default_address_type;
if (!request.params[1].isNull()) {
@@ -256,7 +256,7 @@ RPCHelpMan addmultisigaddress()
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
- std::string label{LabelFromValue(request.params[2])};
+ const std::string& label{LabelFromValue(request.params[2])};
int required = request.params[0].getInt<int>();
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index 1abb2efda..7e5fbfae0 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -140,7 +140,7 @@ RPCHelpMan importprivkey()
EnsureWalletIsUnlocked(*pwallet);
std::string strSecret = request.params[0].get_str();
- std::string strLabel{LabelFromValue(request.params[1])};
+ const std::string& strLabel{LabelFromValue(request.params[1])};
// Whether to perform rescan after import
if (!request.params[2].isNull())
@@ -232,7 +232,7 @@ RPCHelpMan importaddress()
EnsureLegacyScriptPubKeyMan(*pwallet, true);
// Parse label
- std::string strLabel{LabelFromValue(request.params[1])};
+ const std::string& strLabel{LabelFromValue(request.params[1])};
// Whether to perform rescan after import
bool fRescan = true;
@@ -423,7 +423,7 @@ RPCHelpMan importpubkey()
EnsureLegacyScriptPubKeyMan(*pwallet, true);
- std::string strLabel{LabelFromValue(request.params[1])};
+ const std::string& strLabel{LabelFromValue(request.params[1])};
// Whether to perform rescan after import
bool fRescan = true;
@@ -1158,7 +1158,7 @@ static UniValue ProcessImport(CWallet& wallet, const UniValue& data, const int64
if (internal && data.exists("label")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal addresses should not have a label");
}
- std::string label{LabelFromValue(data["label"])};
+ const std::string& label{LabelFromValue(data["label"])};
const bool add_keypool = data.exists("keypool") ? data["keypool"].get_bool() : false;
// Add to keypool only works with privkeys disabled
@@ -1452,7 +1452,7 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
const std::string& descriptor = data["desc"].get_str();
const bool active = data.exists("active") ? data["active"].get_bool() : false;
const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
- std::string label{LabelFromValue(data["label"])};
+ const std::string& label{LabelFromValue(data["label"])};
// Parse descriptor string
FlatSigningProvider keys;
diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp
index 7088ff4ab..9b03782d4 100644
--- a/src/wallet/rpc/transactions.cpp
+++ b/src/wallet/rpc/transactions.cpp
@@ -636,8 +636,8 @@ RPCHelpMan listsinceblock()
bool include_change = (!request.params[4].isNull() && request.params[4].get_bool());
// Only set it if 'label' was provided.
- std::optional<std::string> filter_label = request.params[5].isNull() ? std::nullopt :
- std::optional(LabelFromValue(request.params[5]));
+ const std::optional<std::string>& filter_label = request.params[5].isNull() ? std::nullopt :
+ std::optional{LabelFromValue(request.params[5])};
int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
diff --git a/src/wallet/rpc/util.cpp b/src/wallet/rpc/util.cpp
index 1fdb80630..bc0c284dc 100644
--- a/src/wallet/rpc/util.cpp
+++ b/src/wallet/rpc/util.cpp
@@ -130,11 +130,12 @@ const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wal
return *spk_man;
}
-std::string LabelFromValue(const UniValue& value)
+const std::string& LabelFromValue(const UniValue& value)
{
- if (value.isNull()) return ""; // empty
+ static std::string empty_string;
+ if (value.isNull()) return empty_string;
- std::string label = value.get_str();
+ const std::string& label{value.get_str()};
if (label == "*")
throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
return label;
diff --git a/src/wallet/rpc/util.h b/src/wallet/rpc/util.h
index 87d34f7c1..9dd101167 100644
--- a/src/wallet/rpc/util.h
+++ b/src/wallet/rpc/util.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_WALLET_RPC_UTIL_H
#define BITCOIN_WALLET_RPC_UTIL_H
+#include <attributes.h>
#include <script/script.h>
#include <any>
@@ -40,7 +41,7 @@ const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wal
bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param);
bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet);
-std::string LabelFromValue(const UniValue& value);
+const std::string& LabelFromValue(const UniValue& value LIFETIMEBOUND);
//! Fetch parent descriptors of this scriptPubKey.
void PushParentDescriptors(const CWallet& wallet, const CScript& script_pubkey, UniValue& entry);
</details>