Merge bitcoin/bitcoin#32983: rpc: refactor: use string_view in Arg/MaybeArg

b63428ac9c rpc: refactor: use more (Maybe)Arg<std::string_view> (stickies-v)
037830ca0d refactor: increase string_view usage (stickies-v)
b3bf18f0ba rpc: refactor: use string_view in Arg/MaybeArg (stickies-v)

Pull request description:

  The `RPCHelpMan::{Arg,MaybeArg}` helpers avoid copying (potentially) large strings by returning them as `const std::string*` (`MaybeArg`) or `const std::string&` (`Arg`). For `MaybeArg`, this has the not-so-nice effect that users need to deal with raw pointers, potentially also requiring new functions (e.g. [`EnsureUniqueWalletName` ](https://github.com/bitcoin/bitcoin/pull/32845/commits/d127b25199118756122232d9aafff19f1922869b#diff-d8bfcfbdd5fa7d5c52d38c1fe5eeac9ce5c5a794cdfaf683585140fa70a32374R32)) with raw pointers being implemented.

  This PR aims to improve on this by returning a trivially copyable `std::string_view` (`Arg`) or `std::optional<std::string_view>` (`MaybeArg`), modernizing the interface without introducing any additional copying overhead. In doing so, it also generalizes whether we return by value or by pointer/reference using `std::is_trivially_copyable_v` instead of defining the types manually.

  In cases where functions currently take a `const std::string&` and it would be too much work / touching consensus logic to update them (`signmessage.cpp`), a `std::string` copy is made (which was already happening anyway).

  The last 2 commits increase usage of the `{Arg,MaybeArg}<std::string_view>` helpers, and could be dropped/pruned if anything turns out to be controversial - I just think it's a nice little cleanup.

ACKs for top commit:
  maflcko:
    re-ACK b63428ac9c 🎉
  achow101:
    ACK b63428ac9c
  pablomartin4btc:
    re-ACK [b63428a](https://github.com/bitcoin/bitcoin/commit/b63428ac9ce2c903670409b3e47b9f6730917ae8)
  w0xlt:
    reACK https://github.com/bitcoin/bitcoin/pull/32983/commits/b63428ac9ce2c903670409b3e47b9f6730917ae8

Tree-SHA512: b4942c353a1658c22a88d8c9b402c288ad35265a3b88aa2072b1f9b6d921cd073194ed4b00b807cb48ca440f47c87ef3d8e0dd1a5d814be58fc7743f26288277
This commit is contained in:
Ava Chow committed 2025-10-24 10:33:51 -07:00
commit c6c4edf324
32 files changed
+145 -147

No files matched your search

+2 -1
View File
@@ -12,6 +12,7 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <string> #include <string>
#include <string_view>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -19,7 +20,7 @@ static void ExpandDescriptor(benchmark::Bench& bench)
{ {
ECC_Context ecc_context{}; ECC_Context ecc_context{};
const auto desc_str = "sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))"; constexpr std::string_view desc_str{"sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))"};
const std::pair<int64_t, int64_t> range = {0, 1000}; const std::pair<int64_t, int64_t> range = {0, 1000};
FlatSigningProvider provider; FlatSigningProvider provider;
std::string error; std::string error;
+3 -1
View File
@@ -4,6 +4,7 @@
#include <mutex> #include <mutex>
#include <set> #include <set>
#include <string_view>
#include <blockfilter.h> #include <blockfilter.h>
#include <crypto/siphash.h> #include <crypto/siphash.h>
@@ -151,7 +152,8 @@ const std::string& BlockFilterTypeName(BlockFilterType filter_type)
return it != g_filter_types.end() ? it->second : unknown_retval; return it != g_filter_types.end() ? it->second : unknown_retval;
} }
bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type) { bool BlockFilterTypeByName(std::string_view name, BlockFilterType& filter_type)
{
for (const auto& entry : g_filter_types) { for (const auto& entry : g_filter_types) {
if (entry.second == name) { if (entry.second == name) {
filter_type = entry.first; filter_type = entry.first;
+2 -1
View File
@@ -10,6 +10,7 @@
#include <ios> #include <ios>
#include <set> #include <set>
#include <string> #include <string>
#include <string_view>
#include <unordered_set> #include <unordered_set>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -99,7 +100,7 @@ enum class BlockFilterType : uint8_t
const std::string& BlockFilterTypeName(BlockFilterType filter_type); const std::string& BlockFilterTypeName(BlockFilterType filter_type);
/** Find a filter type by its human-readable name. */ /** Find a filter type by its human-readable name. */
bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type); bool BlockFilterTypeByName(std::string_view name, BlockFilterType& filter_type);
/** Get a list of known filter types. */ /** Get a list of known filter types. */
const std::set<BlockFilterType>& AllBlockFilterTypes(); const std::set<BlockFilterType>& AllBlockFilterTypes();
+2 -1
View File
@@ -16,6 +16,7 @@
#include <cassert> #include <cassert>
#include <map> #include <map>
#include <string> #include <string>
#include <string_view>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -91,7 +92,7 @@ std::string InvalidEstimateModeErrorMessage()
return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\""; return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\"";
} }
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) bool FeeModeFromString(std::string_view mode_string, FeeEstimateMode& fee_estimate_mode)
{ {
auto searchkey = ToUpper(mode_string); auto searchkey = ToUpper(mode_string);
for (const auto& pair : FeeModeMap()) { for (const auto& pair : FeeModeMap()) {
+2 -1
View File
@@ -12,6 +12,7 @@
#define BITCOIN_COMMON_MESSAGES_H #define BITCOIN_COMMON_MESSAGES_H
#include <string> #include <string>
#include <string_view>
struct bilingual_str; struct bilingual_str;
@@ -23,7 +24,7 @@ enum class TransactionError;
namespace common { namespace common {
enum class PSBTError; enum class PSBTError;
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode); bool FeeModeFromString(std::string_view mode_string, FeeEstimateMode& fee_estimate_mode);
std::string StringForFeeReason(FeeReason reason); std::string StringForFeeReason(FeeReason reason);
std::string FeeModes(const std::string& delimiter); std::string FeeModes(const std::string& delimiter);
std::string FeeModeInfo(std::pair<std::string, FeeEstimateMode>& mode); std::string FeeModeInfo(std::pair<std::string, FeeEstimateMode>& mode);
+6 -5
View File
@@ -39,11 +39,12 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cstring>
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <cstring>
#include <functional> #include <functional>
#include <optional> #include <optional>
#include <string_view>
#include <unordered_map> #include <unordered_map>
TRACEPOINT_SEMAPHORE(net, closed_connection); TRACEPOINT_SEMAPHORE(net, closed_connection);
@@ -331,7 +332,7 @@ bool IsLocal(const CService& addr)
return mapLocalHost.count(addr) > 0; return mapLocalHost.count(addr) > 0;
} }
bool CConnman::AlreadyConnectedToHost(const std::string& host) const bool CConnman::AlreadyConnectedToHost(std::string_view host) const
{ {
LOCK(m_nodes_mutex); LOCK(m_nodes_mutex);
return std::ranges::any_of(m_nodes, [&host](CNode* node) { return node->m_addr_name == host; }); return std::ranges::any_of(m_nodes, [&host](CNode* node) { return node->m_addr_name == host; });
@@ -3589,11 +3590,11 @@ bool CConnman::AddNode(const AddedNodeParams& add)
return true; return true;
} }
bool CConnman::RemoveAddedNode(const std::string& strNode) bool CConnman::RemoveAddedNode(std::string_view node)
{ {
LOCK(m_added_nodes_mutex); LOCK(m_added_nodes_mutex);
for (auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) { for (auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) {
if (strNode == it->m_added_node) { if (node == it->m_added_node) {
m_added_node_params.erase(it); m_added_node_params.erase(it);
return true; return true;
} }
@@ -3652,7 +3653,7 @@ void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats) const
} }
} }
bool CConnman::DisconnectNode(const std::string& strNode) bool CConnman::DisconnectNode(std::string_view strNode)
{ {
LOCK(m_nodes_mutex); LOCK(m_nodes_mutex);
auto it = std::ranges::find_if(m_nodes, [&strNode](CNode* node) { return node->m_addr_name == strNode; }); auto it = std::ranges::find_if(m_nodes, [&strNode](CNode* node) { return node->m_addr_name == strNode; });
+4 -3
View File
@@ -43,6 +43,7 @@
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <queue> #include <queue>
#include <string_view>
#include <thread> #include <thread>
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
@@ -1248,7 +1249,7 @@ public:
int GetExtraBlockRelayCount() const; int GetExtraBlockRelayCount() const;
bool AddNode(const AddedNodeParams& add) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); bool AddNode(const AddedNodeParams& add) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
bool RemoveAddedNode(const std::string& node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); bool RemoveAddedNode(std::string_view node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
bool AddedNodesContain(const CAddress& addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); bool AddedNodesContain(const CAddress& addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
std::vector<AddedNodeInfo> GetAddedNodeInfo(bool include_connected) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); std::vector<AddedNodeInfo> GetAddedNodeInfo(bool include_connected) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
@@ -1271,7 +1272,7 @@ public:
std::map<CNetAddr, LocalServiceInfo> getNetLocalAddresses() const; std::map<CNetAddr, LocalServiceInfo> getNetLocalAddresses() const;
uint32_t GetMappedAS(const CNetAddr& addr) const; uint32_t GetMappedAS(const CNetAddr& addr) const;
void GetNodeStats(std::vector<CNodeStats>& vstats) const; void GetNodeStats(std::vector<CNodeStats>& vstats) const;
bool DisconnectNode(const std::string& node); bool DisconnectNode(std::string_view node);
bool DisconnectNode(const CSubNet& subnet); bool DisconnectNode(const CSubNet& subnet);
bool DisconnectNode(const CNetAddr& addr); bool DisconnectNode(const CNetAddr& addr);
bool DisconnectNode(NodeId id); bool DisconnectNode(NodeId id);
@@ -1403,7 +1404,7 @@ private:
* @param[in] host String of the form "host[:port]", e.g. "localhost" or "localhost:8333" or "1.2.3.4:8333". * @param[in] host String of the form "host[:port]", e.g. "localhost" or "localhost:8333" or "1.2.3.4:8333".
* @return true if connected to `host`. * @return true if connected to `host`.
*/ */
bool AlreadyConnectedToHost(const std::string& host) const; bool AlreadyConnectedToHost(std::string_view host) const;
/** /**
* Determine whether we're already connected to a given address:port. * Determine whether we're already connected to a given address:port.
+8 -12
View File
@@ -18,6 +18,7 @@
#include <cstdint> #include <cstdint>
#include <ios> #include <ios>
#include <iterator> #include <iterator>
#include <string_view>
#include <tuple> #include <tuple>
using util::ContainsNoNUL; using util::ContainsNoNUL;
@@ -208,7 +209,7 @@ static void Checksum(std::span<const uint8_t> addr_pubkey, uint8_t (&checksum)[C
}; // namespace torv3 }; // namespace torv3
bool CNetAddr::SetSpecial(const std::string& addr) bool CNetAddr::SetSpecial(std::string_view addr)
{ {
if (!ContainsNoNUL(addr)) { if (!ContainsNoNUL(addr)) {
return false; return false;
@@ -225,16 +226,11 @@ bool CNetAddr::SetSpecial(const std::string& addr)
return false; return false;
} }
bool CNetAddr::SetTor(const std::string& addr) bool CNetAddr::SetTor(std::string_view addr)
{ {
static const char* suffix{".onion"}; if (!addr.ends_with(".onion")) return false;
static constexpr size_t suffix_len{6}; addr.remove_suffix(6);
auto input = DecodeBase32(addr);
if (addr.size() <= suffix_len || addr.substr(addr.size() - suffix_len) != suffix) {
return false;
}
auto input = DecodeBase32(std::string_view{addr}.substr(0, addr.size() - suffix_len));
if (!input) { if (!input) {
return false; return false;
@@ -264,7 +260,7 @@ bool CNetAddr::SetTor(const std::string& addr)
return false; return false;
} }
bool CNetAddr::SetI2P(const std::string& addr) bool CNetAddr::SetI2P(std::string_view addr)
{ {
// I2P addresses that we support consist of 52 base32 characters + ".b32.i2p". // I2P addresses that we support consist of 52 base32 characters + ".b32.i2p".
static constexpr size_t b32_len{52}; static constexpr size_t b32_len{52};
@@ -277,7 +273,7 @@ bool CNetAddr::SetI2P(const std::string& addr)
// Remove the ".b32.i2p" suffix and pad to a multiple of 8 chars, so DecodeBase32() // Remove the ".b32.i2p" suffix and pad to a multiple of 8 chars, so DecodeBase32()
// can decode it. // can decode it.
const std::string b32_padded = addr.substr(0, b32_len) + "===="; const std::string b32_padded{tfm::format("%s====", addr.substr(0, b32_len))};
auto address_bytes = DecodeBase32(b32_padded); auto address_bytes = DecodeBase32(b32_padded);
+4 -3
View File
@@ -18,6 +18,7 @@
#include <cstdint> #include <cstdint>
#include <ios> #include <ios>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
/** /**
@@ -151,7 +152,7 @@ public:
* @returns Whether the operation was successful. * @returns Whether the operation was successful.
* @see CNetAddr::IsTor(), CNetAddr::IsI2P() * @see CNetAddr::IsTor(), CNetAddr::IsI2P()
*/ */
bool SetSpecial(const std::string& addr); bool SetSpecial(std::string_view addr);
bool IsBindAny() const; // INADDR_ANY equivalent bool IsBindAny() const; // INADDR_ANY equivalent
[[nodiscard]] bool IsIPv4() const { return m_net == NET_IPV4; } // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) [[nodiscard]] bool IsIPv4() const { return m_net == NET_IPV4; } // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
@@ -279,7 +280,7 @@ private:
* @returns Whether the operation was successful. * @returns Whether the operation was successful.
* @see CNetAddr::IsTor() * @see CNetAddr::IsTor()
*/ */
bool SetTor(const std::string& addr); bool SetTor(std::string_view addr);
/** /**
* Parse an I2P address and set this object to it. * Parse an I2P address and set this object to it.
@@ -288,7 +289,7 @@ private:
* @returns Whether the operation was successful. * @returns Whether the operation was successful.
* @see CNetAddr::IsI2P() * @see CNetAddr::IsI2P()
*/ */
bool SetI2P(const std::string& addr); bool SetI2P(std::string_view addr);
/** /**
* Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes). * Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes).
+1 -1
View File
@@ -20,7 +20,7 @@ static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32";
static const std::string OUTPUT_TYPE_STRING_BECH32M = "bech32m"; static const std::string OUTPUT_TYPE_STRING_BECH32M = "bech32m";
static const std::string OUTPUT_TYPE_STRING_UNKNOWN = "unknown"; static const std::string OUTPUT_TYPE_STRING_UNKNOWN = "unknown";
std::optional<OutputType> ParseOutputType(const std::string& type) std::optional<OutputType> ParseOutputType(std::string_view type)
{ {
if (type == OUTPUT_TYPE_STRING_LEGACY) { if (type == OUTPUT_TYPE_STRING_LEGACY) {
return OutputType::LEGACY; return OutputType::LEGACY;
+2 -1
View File
@@ -12,6 +12,7 @@
#include <array> #include <array>
#include <optional> #include <optional>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
enum class OutputType { enum class OutputType {
@@ -29,7 +30,7 @@ static constexpr auto OUTPUT_TYPES = std::array{
OutputType::BECH32M, OutputType::BECH32M,
}; };
std::optional<OutputType> ParseOutputType(const std::string& str); std::optional<OutputType> ParseOutputType(std::string_view str);
const std::string& FormatOutputType(OutputType type); const std::string& FormatOutputType(OutputType type);
std::string FormatAllOutputTypes(); std::string FormatAllOutputTypes();
+20 -20
View File
@@ -40,6 +40,7 @@
#include <serialize.h> #include <serialize.h>
#include <streams.h> #include <streams.h>
#include <sync.h> #include <sync.h>
#include <tinyformat.h>
#include <txdb.h> #include <txdb.h>
#include <txmempool.h> #include <txmempool.h>
#include <undo.h> #include <undo.h>
@@ -60,6 +61,8 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <string>
#include <string_view>
#include <vector> #include <vector>
using kernel::CCoinsStats; using kernel::CCoinsStats;
@@ -936,7 +939,7 @@ static RPCHelpMan pruneblockchain()
}; };
} }
CoinStatsHashType ParseHashType(const std::string& hash_type_input) CoinStatsHashType ParseHashType(std::string_view hash_type_input)
{ {
if (hash_type_input == "hash_serialized_3") { if (hash_type_input == "hash_serialized_3") {
return CoinStatsHashType::HASH_SERIALIZED; return CoinStatsHashType::HASH_SERIALIZED;
@@ -1038,7 +1041,7 @@ static RPCHelpMan gettxoutsetinfo()
UniValue ret(UniValue::VOBJ); UniValue ret(UniValue::VOBJ);
const CBlockIndex* pindex{nullptr}; const CBlockIndex* pindex{nullptr};
const CoinStatsHashType hash_type{request.params[0].isNull() ? CoinStatsHashType::HASH_SERIALIZED : ParseHashType(request.params[0].get_str())}; const CoinStatsHashType hash_type{ParseHashType(self.Arg<std::string_view>("hash_type"))};
bool index_requested = request.params[2].isNull() || request.params[2].get_bool(); bool index_requested = request.params[2].isNull() || request.params[2].get_bool();
NodeContext& node = EnsureAnyNodeContext(request.context); NodeContext& node = EnsureAnyNodeContext(request.context);
@@ -2328,7 +2331,7 @@ static RPCHelpMan scantxoutset()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
const auto action{self.Arg<std::string>("action")}; const auto action{self.Arg<std::string_view>("action")};
if (action == "status") { if (action == "status") {
CoinsViewScanReserver reserver; CoinsViewScanReserver reserver;
if (reserver.reserve()) { if (reserver.reserve()) {
@@ -2524,7 +2527,8 @@ static RPCHelpMan scanblocks()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
UniValue ret(UniValue::VOBJ); UniValue ret(UniValue::VOBJ);
if (request.params[0].get_str() == "status") { auto action{self.Arg<std::string_view>("action")};
if (action == "status") {
BlockFiltersScanReserver reserver; BlockFiltersScanReserver reserver;
if (reserver.reserve()) { if (reserver.reserve()) {
// no scan in progress // no scan in progress
@@ -2533,7 +2537,7 @@ static RPCHelpMan scanblocks()
ret.pushKV("progress", g_scanfilter_progress.load()); ret.pushKV("progress", g_scanfilter_progress.load());
ret.pushKV("current_height", g_scanfilter_progress_height.load()); ret.pushKV("current_height", g_scanfilter_progress_height.load());
return ret; return ret;
} else if (request.params[0].get_str() == "abort") { } else if (action == "abort") {
BlockFiltersScanReserver reserver; BlockFiltersScanReserver reserver;
if (reserver.reserve()) { if (reserver.reserve()) {
// reserve was possible which means no scan was running // reserve was possible which means no scan was running
@@ -2542,12 +2546,12 @@ static RPCHelpMan scanblocks()
// set the abort flag // set the abort flag
g_scanfilter_should_abort_scan = true; g_scanfilter_should_abort_scan = true;
return true; return true;
} else if (request.params[0].get_str() == "start") { } else if (action == "start") {
BlockFiltersScanReserver reserver; BlockFiltersScanReserver reserver;
if (!reserver.reserve()) { if (!reserver.reserve()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\""); throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
} }
const std::string filtertype_name{request.params[4].isNull() ? "basic" : request.params[4].get_str()}; auto filtertype_name{self.Arg<std::string_view>("filtertype")};
BlockFilterType filtertype; BlockFilterType filtertype;
if (!BlockFilterTypeByName(filtertype_name, filtertype)) { if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
@@ -2559,7 +2563,7 @@ static RPCHelpMan scanblocks()
BlockFilterIndex* index = GetBlockFilterIndex(filtertype); BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
if (!index) { if (!index) {
throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name); throw JSONRPCError(RPC_MISC_ERROR, tfm::format("Index is not enabled for filtertype %s", filtertype_name));
} }
NodeContext& node = EnsureAnyNodeContext(request.context); NodeContext& node = EnsureAnyNodeContext(request.context);
@@ -2658,9 +2662,8 @@ static RPCHelpMan scanblocks()
ret.pushKV("to_height", start_index->nHeight); // start_index is always the last scanned block here ret.pushKV("to_height", start_index->nHeight); // start_index is always the last scanned block here
ret.pushKV("relevant_blocks", std::move(blocks)); ret.pushKV("relevant_blocks", std::move(blocks));
ret.pushKV("completed", completed); ret.pushKV("completed", completed);
} } else {
else { throw JSONRPCError(RPC_INVALID_PARAMETER, tfm::format("Invalid action '%s'", action));
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", request.params[0].get_str()));
} }
return ret; return ret;
}, },
@@ -2925,10 +2928,7 @@ static RPCHelpMan getblockfilter()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
uint256 block_hash = ParseHashV(request.params[0], "blockhash"); uint256 block_hash = ParseHashV(request.params[0], "blockhash");
std::string filtertype_name = BlockFilterTypeName(BlockFilterType::BASIC); auto filtertype_name{self.Arg<std::string_view>("filtertype")};
if (!request.params[1].isNull()) {
filtertype_name = request.params[1].get_str();
}
BlockFilterType filtertype; BlockFilterType filtertype;
if (!BlockFilterTypeByName(filtertype_name, filtertype)) { if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
@@ -2937,7 +2937,7 @@ static RPCHelpMan getblockfilter()
BlockFilterIndex* index = GetBlockFilterIndex(filtertype); BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
if (!index) { if (!index) {
throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name); throw JSONRPCError(RPC_MISC_ERROR, tfm::format("Index is not enabled for filtertype %s", filtertype_name));
} }
const CBlockIndex* block_index; const CBlockIndex* block_index;
@@ -3064,7 +3064,7 @@ static RPCHelpMan dumptxoutset()
NodeContext& node = EnsureAnyNodeContext(request.context); NodeContext& node = EnsureAnyNodeContext(request.context);
const CBlockIndex* tip{WITH_LOCK(::cs_main, return node.chainman->ActiveChain().Tip())}; const CBlockIndex* tip{WITH_LOCK(::cs_main, return node.chainman->ActiveChain().Tip())};
const CBlockIndex* target_index{nullptr}; const CBlockIndex* target_index{nullptr};
const std::string snapshot_type{self.Arg<std::string>("type")}; const auto snapshot_type{self.Arg<std::string_view>("type")};
const UniValue options{request.params[2].isNull() ? UniValue::VOBJ : request.params[2]}; const UniValue options{request.params[2].isNull() ? UniValue::VOBJ : request.params[2]};
if (options.exists("rollback")) { if (options.exists("rollback")) {
if (!snapshot_type.empty() && snapshot_type != "rollback") { if (!snapshot_type.empty() && snapshot_type != "rollback") {
@@ -3083,10 +3083,10 @@ static RPCHelpMan dumptxoutset()
} }
const ArgsManager& args{EnsureAnyArgsman(request.context)}; const ArgsManager& args{EnsureAnyArgsman(request.context)};
const fs::path path = fsbridge::AbsPathJoin(args.GetDataDirNet(), fs::u8path(request.params[0].get_str())); const fs::path path = fsbridge::AbsPathJoin(args.GetDataDirNet(), fs::u8path(self.Arg<std::string_view>("path")));
// Write to a temporary path and then move into `path` on completion // Write to a temporary path and then move into `path` on completion
// to avoid confusion due to an interruption. // to avoid confusion due to an interruption.
const fs::path temppath = fsbridge::AbsPathJoin(args.GetDataDirNet(), fs::u8path(request.params[0].get_str() + ".incomplete")); const fs::path temppath = path + ".incomplete";
if (fs::exists(path)) { if (fs::exists(path)) {
throw JSONRPCError( throw JSONRPCError(
@@ -3355,7 +3355,7 @@ static RPCHelpMan loadtxoutset()
{ {
NodeContext& node = EnsureAnyNodeContext(request.context); NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node); ChainstateManager& chainman = EnsureChainman(node);
const fs::path path{AbsPathForConfigVal(EnsureArgsman(node), fs::u8path(self.Arg<std::string>("path")))}; const fs::path path{AbsPathForConfigVal(EnsureArgsman(node), fs::u8path(self.Arg<std::string_view>("path")))};
FILE* file{fsbridge::fopen(path, "rb")}; FILE* file{fsbridge::fopen(path, "rb")};
AutoFile afile{file}; AutoFile afile{file};
+3 -5
View File
@@ -21,6 +21,7 @@
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <string> #include <string>
#include <string_view>
using common::FeeModeFromString; using common::FeeModeFromString;
using common::FeeModesDetail; using common::FeeModesDetail;
@@ -67,18 +68,15 @@ static RPCHelpMan estimatesmartfee()
CHECK_NONFATAL(mempool.m_opts.signals)->SyncWithValidationInterfaceQueue(); CHECK_NONFATAL(mempool.m_opts.signals)->SyncWithValidationInterfaceQueue();
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target); unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
bool conservative = false;
if (!request.params[1].isNull()) {
FeeEstimateMode fee_mode; FeeEstimateMode fee_mode;
if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) { if (!FeeModeFromString(self.Arg<std::string_view>("estimate_mode"), fee_mode)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage()); throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage());
} }
if (fee_mode == FeeEstimateMode::CONSERVATIVE) conservative = true;
}
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
UniValue errors(UniValue::VARR); UniValue errors(UniValue::VARR);
FeeCalculation feeCalc; FeeCalculation feeCalc;
bool conservative{fee_mode == FeeEstimateMode::CONSERVATIVE};
CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)}; CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)};
if (feeRate != CFeeRate(0)) { if (feeRate != CFeeRate(0)) {
CFeeRate min_mempool_feerate{mempool.GetMinFee()}; CFeeRate min_mempool_feerate{mempool.GetMinFee()};
+2 -1
View File
@@ -28,6 +28,7 @@
#include <util/time.h> #include <util/time.h>
#include <util/vector.h> #include <util/vector.h>
#include <string_view>
#include <utility> #include <utility>
using node::DumpMempool; using node::DumpMempool;
@@ -768,7 +769,7 @@ static RPCHelpMan importmempool()
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Can only import the mempool after the block download and sync is done."); throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Can only import the mempool after the block download and sync is done.");
} }
const fs::path load_path{fs::u8path(request.params[0].get_str())}; const fs::path load_path{fs::u8path(self.Arg<std::string_view>("filepath"))};
const UniValue& use_current_time{request.params[1]["use_current_time"]}; const UniValue& use_current_time{request.params[1]["use_current_time"]};
const UniValue& apply_fee_delta{request.params[1]["apply_fee_delta_priority"]}; const UniValue& apply_fee_delta{request.params[1]["apply_fee_delta_priority"]};
const UniValue& apply_unbroadcast{request.params[1]["apply_unbroadcast_set"]}; const UniValue& apply_unbroadcast{request.params[1]["apply_unbroadcast_set"]};
+2 -2
View File
@@ -181,7 +181,7 @@ static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const
return blockHashes; return blockHashes;
} }
static bool getScriptFromDescriptor(const std::string& descriptor, CScript& script, std::string& error) static bool getScriptFromDescriptor(std::string_view descriptor, CScript& script, std::string& error)
{ {
FlatSigningProvider key_provider; FlatSigningProvider key_provider;
const auto descs = Parse(descriptor, key_provider, error, /* require_checksum = */ false); const auto descs = Parse(descriptor, key_provider, error, /* require_checksum = */ false);
@@ -241,7 +241,7 @@ static RPCHelpMan generatetodescriptor()
CScript coinbase_output_script; CScript coinbase_output_script;
std::string error; std::string error;
if (!getScriptFromDescriptor(self.Arg<std::string>("descriptor"), coinbase_output_script, error)) { if (!getScriptFromDescriptor(self.Arg<std::string_view>("descriptor"), coinbase_output_script, error)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
} }
+27 -34
View File
@@ -36,11 +36,11 @@
#include <optional> #include <optional>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
using node::NodeContext; using node::NodeContext;
using util::Join; using util::Join;
using util::TrimString;
const std::vector<std::string> CONNECTION_TYPE_DOC{ const std::vector<std::string> CONNECTION_TYPE_DOC{
"outbound-full-relay (default automatic connections)", "outbound-full-relay (default automatic connections)",
@@ -333,7 +333,7 @@ static RPCHelpMan addnode()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
const auto command{self.Arg<std::string>("command")}; const auto command{self.Arg<std::string_view>("command")};
if (command != "onetry" && command != "add" && command != "remove") { if (command != "onetry" && command != "add" && command != "remove") {
throw std::runtime_error( throw std::runtime_error(
self.ToString()); self.ToString());
@@ -342,7 +342,7 @@ static RPCHelpMan addnode()
NodeContext& node = EnsureAnyNodeContext(request.context); NodeContext& node = EnsureAnyNodeContext(request.context);
CConnman& connman = EnsureConnman(node); CConnman& connman = EnsureConnman(node);
const auto node_arg{self.Arg<std::string>("node")}; const auto node_arg{self.Arg<std::string_view>("node")};
bool node_v2transport = connman.GetLocalServices() & NODE_P2P_V2; bool node_v2transport = connman.GetLocalServices() & NODE_P2P_V2;
bool use_v2transport = self.MaybeArg<bool>("v2transport").value_or(node_v2transport); bool use_v2transport = self.MaybeArg<bool>("v2transport").value_or(node_v2transport);
@@ -353,13 +353,13 @@ static RPCHelpMan addnode()
if (command == "onetry") if (command == "onetry")
{ {
CAddress addr; CAddress addr;
connman.OpenNetworkConnection(addr, /*fCountFailure=*/false, /*grant_outbound=*/{}, node_arg.c_str(), ConnectionType::MANUAL, use_v2transport); connman.OpenNetworkConnection(addr, /*fCountFailure=*/false, /*grant_outbound=*/{}, std::string{node_arg}.c_str(), ConnectionType::MANUAL, use_v2transport);
return UniValue::VNULL; return UniValue::VNULL;
} }
if (command == "add") if (command == "add")
{ {
if (!connman.AddNode({node_arg, use_v2transport})) { if (!connman.AddNode({std::string{node_arg}, use_v2transport})) {
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added"); throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
} }
} }
@@ -402,7 +402,7 @@ static RPCHelpMan addconnection()
} }
const std::string address = request.params[0].get_str(); const std::string address = request.params[0].get_str();
const std::string conn_type_in{TrimString(request.params[1].get_str())}; auto conn_type_in{util::TrimStringView(self.Arg<std::string_view>("connection_type"))};
ConnectionType conn_type{}; ConnectionType conn_type{};
if (conn_type_in == "outbound-full-relay") { if (conn_type_in == "outbound-full-relay") {
conn_type = ConnectionType::OUTBOUND_FULL_RELAY; conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
@@ -462,16 +462,15 @@ static RPCHelpMan disconnectnode()
CConnman& connman = EnsureConnman(node); CConnman& connman = EnsureConnman(node);
bool success; bool success;
const UniValue &address_arg = request.params[0]; auto address{self.MaybeArg<std::string_view>("address")};
const UniValue &id_arg = request.params[1]; auto node_id{self.MaybeArg<int64_t>("nodeid")};
if (!address_arg.isNull() && id_arg.isNull()) { if (address && !node_id) {
/* handle disconnect-by-address */ /* handle disconnect-by-address */
success = connman.DisconnectNode(address_arg.get_str()); success = connman.DisconnectNode(*address);
} else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) { } else if (node_id && (!address || address->empty())) {
/* handle disconnect-by-id */ /* handle disconnect-by-id */
NodeId nodeid = (NodeId) id_arg.getInt<int64_t>(); success = connman.DisconnectNode(*node_id);
success = connman.DisconnectNode(nodeid);
} else { } else {
throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided."); throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
} }
@@ -523,10 +522,10 @@ static RPCHelpMan getaddednodeinfo()
std::vector<AddedNodeInfo> vInfo = connman.GetAddedNodeInfo(/*include_connected=*/true); std::vector<AddedNodeInfo> vInfo = connman.GetAddedNodeInfo(/*include_connected=*/true);
if (!request.params[0].isNull()) { if (auto node{self.MaybeArg<std::string_view>("node")}) {
bool found = false; bool found = false;
for (const AddedNodeInfo& info : vInfo) { for (const AddedNodeInfo& info : vInfo) {
if (info.m_params.m_added_node == request.params[0].get_str()) { if (info.m_params.m_added_node == *node) {
vInfo.assign(1, info); vInfo.assign(1, info);
found = true; found = true;
break; break;
@@ -754,10 +753,8 @@ static RPCHelpMan setban()
}, },
[&](const RPCHelpMan& help, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& help, const JSONRPCRequest& request) -> UniValue
{ {
std::string strCommand; auto command{help.Arg<std::string_view>("command")};
if (!request.params[1].isNull()) if (command != "add" && command != "remove") {
strCommand = request.params[1].get_str();
if (strCommand != "add" && strCommand != "remove") {
throw std::runtime_error(help.ToString()); throw std::runtime_error(help.ToString());
} }
NodeContext& node = EnsureAnyNodeContext(request.context); NodeContext& node = EnsureAnyNodeContext(request.context);
@@ -765,25 +762,23 @@ static RPCHelpMan setban()
CSubNet subNet; CSubNet subNet;
CNetAddr netAddr; CNetAddr netAddr;
bool isSubnet = false; std::string subnet_arg{help.Arg<std::string_view>("subnet")};
const bool isSubnet{subnet_arg.find('/') != subnet_arg.npos};
if (request.params[0].get_str().find('/') != std::string::npos)
isSubnet = true;
if (!isSubnet) { if (!isSubnet) {
const std::optional<CNetAddr> addr{LookupHost(request.params[0].get_str(), false)}; const std::optional<CNetAddr> addr{LookupHost(subnet_arg, false)};
if (addr.has_value()) { if (addr.has_value()) {
netAddr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0})); netAddr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
} }
} else {
subNet = LookupSubNet(subnet_arg);
} }
else
subNet = LookupSubNet(request.params[0].get_str());
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) {
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet"); throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
}
if (strCommand == "add") if (command == "add") {
{
if (isSubnet ? banman.IsBanned(subNet) : banman.IsBanned(netAddr)) { if (isSubnet ? banman.IsBanned(subNet) : banman.IsBanned(netAddr)) {
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
} }
@@ -809,9 +804,7 @@ static RPCHelpMan setban()
node.connman->DisconnectNode(netAddr); node.connman->DisconnectNode(netAddr);
} }
} }
} } else if(command == "remove") {
else if(strCommand == "remove")
{
if (!( isSubnet ? banman.Unban(subNet) : banman.Unban(netAddr) )) { if (!( isSubnet ? banman.Unban(subNet) : banman.Unban(netAddr) )) {
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned."); throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");
} }
@@ -1051,11 +1044,11 @@ static RPCHelpMan sendmsgtopeer()
HelpExampleCli("sendmsgtopeer", "0 \"addr\" \"ffffff\"") + HelpExampleRpc("sendmsgtopeer", "0 \"addr\" \"ffffff\"")}, HelpExampleCli("sendmsgtopeer", "0 \"addr\" \"ffffff\"") + HelpExampleRpc("sendmsgtopeer", "0 \"addr\" \"ffffff\"")},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
const NodeId peer_id{request.params[0].getInt<int64_t>()}; const NodeId peer_id{request.params[0].getInt<int64_t>()};
const std::string& msg_type{request.params[1].get_str()}; const auto msg_type{self.Arg<std::string_view>("msg_type")};
if (msg_type.size() > CMessageHeader::MESSAGE_TYPE_SIZE) { if (msg_type.size() > CMessageHeader::MESSAGE_TYPE_SIZE) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Error: msg_type too long, max length is %i", CMessageHeader::MESSAGE_TYPE_SIZE)); throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Error: msg_type too long, max length is %i", CMessageHeader::MESSAGE_TYPE_SIZE));
} }
auto msg{TryParseHex<unsigned char>(request.params[2].get_str())}; auto msg{TryParseHex<unsigned char>(self.Arg<std::string_view>("msg"))};
if (!msg.has_value()) { if (!msg.has_value()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Error parsing input for msg"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Error parsing input for msg");
} }
+5 -3
View File
@@ -21,6 +21,7 @@
#include <rpc/server_util.h> #include <rpc/server_util.h>
#include <rpc/util.h> #include <rpc/util.h>
#include <scheduler.h> #include <scheduler.h>
#include <tinyformat.h>
#include <univalue.h> #include <univalue.h>
#include <util/any.h> #include <util/any.h>
#include <util/check.h> #include <util/check.h>
@@ -30,6 +31,7 @@
#ifdef HAVE_MALLOC_INFO #ifdef HAVE_MALLOC_INFO
#include <malloc.h> #include <malloc.h>
#endif #endif
#include <string_view>
using node::NodeContext; using node::NodeContext;
@@ -176,7 +178,7 @@ static RPCHelpMan getmemoryinfo()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str(); auto mode{self.Arg<std::string_view>("mode")};
if (mode == "stats") { if (mode == "stats") {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("locked", RPCLockedMemoryInfo()); obj.pushKV("locked", RPCLockedMemoryInfo());
@@ -188,7 +190,7 @@ static RPCHelpMan getmemoryinfo()
throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo mode not available"); throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo mode not available");
#endif #endif
} else { } else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode); throw JSONRPCError(RPC_INVALID_PARAMETER, tfm::format("unknown mode %s", mode));
} }
}, },
}; };
@@ -385,7 +387,7 @@ static RPCHelpMan getindexinfo()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
const std::string index_name = request.params[0].isNull() ? "" : request.params[0].get_str(); const std::string index_name{self.MaybeArg<std::string_view>("index_name").value_or("")};
if (g_txindex) { if (g_txindex) {
result.pushKVs(SummaryToJSON(g_txindex->GetSummary(), index_name)); result.pushKVs(SummaryToJSON(g_txindex->GetSummary(), index_name));
+10 -12
View File
@@ -22,6 +22,7 @@
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string> #include <string>
#include <string_view>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
@@ -130,20 +131,17 @@ static RPCHelpMan createmultisig()
} }
// Get the output type // Get the output type
OutputType output_type = OutputType::LEGACY; auto address_type{self.Arg<std::string_view>("address_type")};
if (!request.params[2].isNull()) { auto output_type{ParseOutputType(address_type)};
std::optional<OutputType> parsed = ParseOutputType(request.params[2].get_str()); if (!output_type) {
if (!parsed) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, tfm::format("Unknown address type '%s'", address_type));
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[2].get_str())); } else if (output_type.value() == OutputType::BECH32M) {
} else if (parsed.value() == OutputType::BECH32M) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "createmultisig cannot create bech32m multisig addresses"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "createmultisig cannot create bech32m multisig addresses");
} }
output_type = parsed.value();
}
FlatSigningProvider keystore; FlatSigningProvider keystore;
CScript inner; CScript inner;
const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, keystore, inner); const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type.value(), keystore, inner);
// Make the descriptor // Make the descriptor
std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore); std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore);
@@ -154,7 +152,7 @@ static RPCHelpMan createmultisig()
result.pushKV("descriptor", descriptor->ToString()); result.pushKV("descriptor", descriptor->ToString());
UniValue warnings(UniValue::VARR); UniValue warnings(UniValue::VARR);
if (descriptor->GetOutputType() != output_type) { if (descriptor->GetOutputType() != output_type.value()) {
// Only warns if the user has explicitly chosen an address type we cannot generate // Only warns if the user has explicitly chosen an address type we cannot generate
warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present."); warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
} }
@@ -198,7 +196,7 @@ static RPCHelpMan getdescriptorinfo()
{ {
FlatSigningProvider provider; FlatSigningProvider provider;
std::string error; std::string error;
auto descs = Parse(request.params[0].get_str(), provider, error); auto descs = Parse(self.Arg<std::string_view>("descriptor"), provider, error);
if (descs.empty()) { if (descs.empty()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
} }
@@ -303,7 +301,7 @@ static RPCHelpMan deriveaddresses()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
const std::string desc_str = request.params[0].get_str(); auto desc_str{self.Arg<std::string_view>("descriptor")};
int64_t range_begin = 0; int64_t range_begin = 0;
int64_t range_end = 0; int64_t range_end = 0;
+5 -7
View File
@@ -26,6 +26,7 @@
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <string_view>
#include <unordered_map> #include <unordered_map>
using util::SplitString; using util::SplitString;
@@ -65,7 +66,7 @@ struct RPCCommandExecution
} }
}; };
std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const std::string CRPCTable::help(std::string_view strCommand, const JSONRPCRequest& helpreq) const
{ {
std::string strRet; std::string strRet;
std::string category; std::string category;
@@ -130,16 +131,13 @@ static RPCHelpMan help()
RPCExamples{""}, RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue
{ {
std::string strCommand; auto command{self.MaybeArg<std::string_view>("command")};
if (jsonRequest.params.size() > 0) { if (command == "dump_all_command_conversions") {
strCommand = jsonRequest.params[0].get_str();
}
if (strCommand == "dump_all_command_conversions") {
// Used for testing only, undocumented // Used for testing only, undocumented
return tableRPC.dumpArgMap(jsonRequest); return tableRPC.dumpArgMap(jsonRequest);
} }
return tableRPC.help(strCommand, jsonRequest); return tableRPC.help(command.value_or(""), jsonRequest);
}, },
}; };
} }
+1 -1
View File
@@ -89,7 +89,7 @@ private:
std::map<std::string, std::vector<const CRPCCommand*>> mapCommands; std::map<std::string, std::vector<const CRPCCommand*>> mapCommands;
public: public:
CRPCTable(); CRPCTable();
std::string help(const std::string& name, const JSONRPCRequest& helpreq) const; std::string help(std::string_view name, const JSONRPCRequest& helpreq) const;
/** /**
* Execute a method. * Execute a method.
+3 -5
View File
@@ -38,11 +38,9 @@ static RPCHelpMan verifymessage()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::string strAddress = self.Arg<std::string>("address"); switch (MessageVerify(std::string{self.Arg<std::string_view>("address")},
std::string strSign = self.Arg<std::string>("signature"); std::string{self.Arg<std::string_view>("signature")},
std::string strMessage = self.Arg<std::string>("message"); std::string{self.Arg<std::string_view>("message")})) {
switch (MessageVerify(strAddress, strSign, strMessage)) {
case MessageVerificationResult::ERR_INVALID_ADDRESS: case MessageVerificationResult::ERR_INVALID_ADDRESS:
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
case MessageVerificationResult::ERR_ADDRESS_NO_KEY: case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
+3 -2
View File
@@ -724,7 +724,8 @@ static void CheckRequiredOrDefault(const RPCArg& param)
TMPL_INST(nullptr, const UniValue*, maybe_arg;); TMPL_INST(nullptr, const UniValue*, maybe_arg;);
TMPL_INST(nullptr, std::optional<double>, maybe_arg ? std::optional{maybe_arg->get_real()} : std::nullopt;); TMPL_INST(nullptr, std::optional<double>, maybe_arg ? std::optional{maybe_arg->get_real()} : std::nullopt;);
TMPL_INST(nullptr, std::optional<bool>, maybe_arg ? std::optional{maybe_arg->get_bool()} : std::nullopt;); TMPL_INST(nullptr, std::optional<bool>, maybe_arg ? std::optional{maybe_arg->get_bool()} : std::nullopt;);
TMPL_INST(nullptr, const std::string*, maybe_arg ? &maybe_arg->get_str() : nullptr;); TMPL_INST(nullptr, std::optional<int64_t>, maybe_arg ? std::optional{maybe_arg->getInt<int64_t>()} : std::nullopt;);
TMPL_INST(nullptr, std::optional<std::string_view>, maybe_arg ? std::optional<std::string_view>{maybe_arg->get_str()} : std::nullopt;);
// Required arg or optional arg with default value. // Required arg or optional arg with default value.
TMPL_INST(CheckRequiredOrDefault, const UniValue&, *CHECK_NONFATAL(maybe_arg);); TMPL_INST(CheckRequiredOrDefault, const UniValue&, *CHECK_NONFATAL(maybe_arg););
@@ -732,7 +733,7 @@ TMPL_INST(CheckRequiredOrDefault, bool, CHECK_NONFATAL(maybe_arg)->get_bool(););
TMPL_INST(CheckRequiredOrDefault, int, CHECK_NONFATAL(maybe_arg)->getInt<int>();); TMPL_INST(CheckRequiredOrDefault, int, CHECK_NONFATAL(maybe_arg)->getInt<int>(););
TMPL_INST(CheckRequiredOrDefault, uint64_t, CHECK_NONFATAL(maybe_arg)->getInt<uint64_t>();); TMPL_INST(CheckRequiredOrDefault, uint64_t, CHECK_NONFATAL(maybe_arg)->getInt<uint64_t>(););
TMPL_INST(CheckRequiredOrDefault, uint32_t, CHECK_NONFATAL(maybe_arg)->getInt<uint32_t>();); TMPL_INST(CheckRequiredOrDefault, uint32_t, CHECK_NONFATAL(maybe_arg)->getInt<uint32_t>(););
TMPL_INST(CheckRequiredOrDefault, const std::string&, CHECK_NONFATAL(maybe_arg)->get_str();); TMPL_INST(CheckRequiredOrDefault, std::string_view, CHECK_NONFATAL(maybe_arg)->get_str(););
bool RPCHelpMan::IsValidNumArgs(size_t num_args) const bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
{ {
+5 -5
View File
@@ -445,8 +445,8 @@ public:
{ {
auto i{GetParamIndex(key)}; auto i{GetParamIndex(key)};
// Return argument (required or with default value). // Return argument (required or with default value).
if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) { if constexpr (std::is_trivially_copyable_v<R>) {
// Return numbers by value. // Return trivially copyable types by value.
return ArgValue<R>(i); return ArgValue<R>(i);
} else { } else {
// Return everything else by reference. // Return everything else by reference.
@@ -466,7 +466,7 @@ public:
* *
* The instantiation of this helper for type R must match the corresponding RPCArg::Type. * The instantiation of this helper for type R must match the corresponding RPCArg::Type.
* *
* @return For integral and floating-point types, a std::optional<R> is returned. * @return For trivially copyable types, a std::optional<R> is returned.
* For other types, a R* pointer to the argument is returned. If the * For other types, a R* pointer to the argument is returned. If the
* argument is not provided, std::nullopt or a null pointer is returned. * argument is not provided, std::nullopt or a null pointer is returned.
* *
@@ -477,8 +477,8 @@ public:
{ {
auto i{GetParamIndex(key)}; auto i{GetParamIndex(key)};
// Return optional argument (without default). // Return optional argument (without default).
if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) { if constexpr (std::is_trivially_copyable_v<R>) {
// Return numbers by value, wrapped in optional. // Return trivially copyable types by value, wrapped in optional.
return ArgValue<std::optional<R>>(i); return ArgValue<std::optional<R>>(i);
} else { } else {
// Return other types by pointer. // Return other types by pointer.
+4 -5
View File
@@ -2730,13 +2730,12 @@ bool CheckChecksum(std::span<const char>& sp, bool require_checksum, std::string
return true; return true;
} }
std::vector<std::unique_ptr<Descriptor>> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum) std::vector<std::unique_ptr<Descriptor>> Parse(std::span<const char> descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum)
{ {
std::span<const char> sp{descriptor}; if (!CheckChecksum(descriptor, require_checksum, error)) return {};
if (!CheckChecksum(sp, require_checksum, error)) return {};
uint32_t key_exp_index = 0; uint32_t key_exp_index = 0;
auto ret = ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out, error); auto ret = ParseScript(key_exp_index, descriptor, ParseScriptContext::TOP, out, error);
if (sp.size() == 0 && !ret.empty()) { if (descriptor.empty() && !ret.empty()) {
std::vector<std::unique_ptr<Descriptor>> descs; std::vector<std::unique_ptr<Descriptor>> descs;
descs.reserve(ret.size()); descs.reserve(ret.size());
for (auto& r : ret) { for (auto& r : ret) {
+1 -1
View File
@@ -175,7 +175,7 @@ struct Descriptor {
* If a parse error occurs, or the checksum is missing/invalid, or anything * If a parse error occurs, or the checksum is missing/invalid, or anything
* else is wrong, an empty vector is returned. * else is wrong, an empty vector is returned.
*/ */
std::vector<std::unique_ptr<Descriptor>> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false); std::vector<std::unique_ptr<Descriptor>> Parse(std::span<const char> descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false);
/** Get the checksum for a `descriptor`. /** Get the checksum for a `descriptor`.
* *
+5 -5
View File
@@ -14,6 +14,7 @@
#include <util/time.h> #include <util/time.h>
#include <any> #include <any>
#include <string_view>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
@@ -621,9 +622,9 @@ BOOST_AUTO_TEST_CASE(rpc_arg_helper)
//! Check that `self.Arg` returns the same value as the `request.params` accessors //! Check that `self.Arg` returns the same value as the `request.params` accessors
RPCHelpMan::RPCMethodImpl check_positional = [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { RPCHelpMan::RPCMethodImpl check_positional = [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
BOOST_CHECK_EQUAL(self.Arg<int>("req_int"), request.params[0].getInt<int>()); BOOST_CHECK_EQUAL(self.Arg<int>("req_int"), request.params[0].getInt<int>());
BOOST_CHECK_EQUAL(self.Arg<std::string>("req_str"), request.params[1].get_str()); BOOST_CHECK_EQUAL(self.Arg<std::string_view>("req_str"), request.params[1].get_str());
BOOST_CHECK_EQUAL(self.Arg<uint64_t>("def_uint64_t"), request.params[2].isNull() ? DEFAULT_UINT64_T : request.params[2].getInt<uint64_t>()); BOOST_CHECK_EQUAL(self.Arg<uint64_t>("def_uint64_t"), request.params[2].isNull() ? DEFAULT_UINT64_T : request.params[2].getInt<uint64_t>());
BOOST_CHECK_EQUAL(self.Arg<std::string>("def_string"), request.params[3].isNull() ? DEFAULT_STRING : request.params[3].get_str()); BOOST_CHECK_EQUAL(self.Arg<std::string_view>("def_string"), request.params[3].isNull() ? DEFAULT_STRING : request.params[3].get_str());
BOOST_CHECK_EQUAL(self.Arg<bool>("def_bool"), request.params[4].isNull() ? DEFAULT_BOOL : request.params[4].get_bool()); BOOST_CHECK_EQUAL(self.Arg<bool>("def_bool"), request.params[4].isNull() ? DEFAULT_BOOL : request.params[4].get_bool());
if (!request.params[5].isNull()) { if (!request.params[5].isNull()) {
BOOST_CHECK_EQUAL(self.MaybeArg<double>("opt_double").value(), request.params[5].get_real()); BOOST_CHECK_EQUAL(self.MaybeArg<double>("opt_double").value(), request.params[5].get_real());
@@ -631,10 +632,9 @@ BOOST_AUTO_TEST_CASE(rpc_arg_helper)
BOOST_CHECK(!self.MaybeArg<double>("opt_double")); BOOST_CHECK(!self.MaybeArg<double>("opt_double"));
} }
if (!request.params[6].isNull()) { if (!request.params[6].isNull()) {
BOOST_CHECK(self.MaybeArg<std::string>("opt_string")); BOOST_CHECK_EQUAL(self.MaybeArg<std::string_view>("opt_string"), request.params[6].get_str());
BOOST_CHECK_EQUAL(*self.MaybeArg<std::string>("opt_string"), request.params[6].get_str());
} else { } else {
BOOST_CHECK(!self.MaybeArg<std::string>("opt_string")); BOOST_CHECK(!self.MaybeArg<std::string_view>("opt_string"));
} }
return UniValue{}; return UniValue{};
}; };
+2 -1
View File
@@ -14,6 +14,7 @@
#include <ios> #include <ios>
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <string_view>
#include <system_error> #include <system_error>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@@ -77,7 +78,7 @@ public:
} }
}; };
static inline path u8path(const std::string& utf8_str) static inline path u8path(std::string_view utf8_str)
{ {
return std::filesystem::path(std::u8string{utf8_str.begin(), utf8_str.end()}); return std::filesystem::path(std::u8string{utf8_str.begin(), utf8_str.end()});
} }
+1 -2
View File
@@ -196,8 +196,7 @@ RPCHelpMan getbalance()
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
const auto dummy_value{self.MaybeArg<std::string>("dummy")}; if (self.MaybeArg<std::string_view>("dummy").value_or("*") != "*") {
if (dummy_value && *dummy_value != "*") {
throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\"."); throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
} }
+3 -2
View File
@@ -11,6 +11,7 @@
#include <wallet/context.h> #include <wallet/context.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <optional>
#include <string_view> #include <string_view>
#include <univalue.h> #include <univalue.h>
@@ -29,7 +30,7 @@ bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param) {
return avoid_reuse; return avoid_reuse;
} }
std::string EnsureUniqueWalletName(const JSONRPCRequest& request, const std::string* wallet_name) std::string EnsureUniqueWalletName(const JSONRPCRequest& request, std::optional<std::string_view> wallet_name)
{ {
std::string endpoint_wallet; std::string endpoint_wallet;
if (GetWalletNameFromJSONRPCRequest(request, endpoint_wallet)) { if (GetWalletNameFromJSONRPCRequest(request, endpoint_wallet)) {
@@ -47,7 +48,7 @@ std::string EnsureUniqueWalletName(const JSONRPCRequest& request, const std::str
"Either the RPC endpoint wallet or the wallet name parameter must be provided"); "Either the RPC endpoint wallet or the wallet name parameter must be provided");
} }
return *wallet_name; return std::string{*wallet_name};
} }
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name) bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
+3 -1
View File
@@ -11,7 +11,9 @@
#include <any> #include <any>
#include <memory> #include <memory>
#include <optional>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
class JSONRPCRequest; class JSONRPCRequest;
@@ -42,7 +44,7 @@ bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string&
* Ensures that a wallet name is specified across the endpoint and wallet_name. * Ensures that a wallet name is specified across the endpoint and wallet_name.
* Throws `RPC_INVALID_PARAMETER` if none or different wallet names are specified. * Throws `RPC_INVALID_PARAMETER` if none or different wallet names are specified.
*/ */
std::string EnsureUniqueWalletName(const JSONRPCRequest& request, const std::string* wallet_name); std::string EnsureUniqueWalletName(const JSONRPCRequest& request, std::optional<std::string_view> wallet_name);
void EnsureWalletIsUnlocked(const CWallet&); void EnsureWalletIsUnlocked(const CWallet&);
WalletContext& EnsureWalletContext(const std::any& context); WalletContext& EnsureWalletContext(const std::any& context);
+3 -2
View File
@@ -19,6 +19,7 @@
#include <wallet/walletutil.h> #include <wallet/walletutil.h>
#include <optional> #include <optional>
#include <string_view>
namespace wallet { namespace wallet {
@@ -456,7 +457,7 @@ static RPCHelpMan unloadwallet()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string>("wallet_name"))}; const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string_view>("wallet_name"))};
WalletContext& context = EnsureWalletContext(request.context); WalletContext& context = EnsureWalletContext(request.context);
std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name); std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
@@ -613,7 +614,7 @@ static RPCHelpMan migratewallet()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string>("wallet_name"))}; const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string_view>("wallet_name"))};
SecureString wallet_pass; SecureString wallet_pass;
wallet_pass.reserve(100); wallet_pass.reserve(100);
+1 -1
View File
@@ -17,7 +17,7 @@ static std::string TestWalletName(const std::string& endpoint, std::optional<std
{ {
JSONRPCRequest req; JSONRPCRequest req;
req.URI = endpoint; req.URI = endpoint;
return EnsureUniqueWalletName(req, parameter ? &*parameter : nullptr); return EnsureUniqueWalletName(req, parameter);
} }
BOOST_FIXTURE_TEST_SUITE(wallet_rpc_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(wallet_rpc_tests, BasicTestingSetup)