From 747cff842481153357199bf9a81b5a4d82ea91fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Wed, 19 Aug 2026 22:05:42 -0700 Subject: [PATCH] rpc: avoid quadratic output lookups `ParseOutputs` iterates a `UniValue` object's keys and looks up each value by key. Each lookup scans the key vector from the beginning, making the lookup work quadratic. Walk the parallel key and value vectors together to avoid repeated scans. This preserves output order and validation behavior. --- src/rpc/rawtransaction_util.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp index c90ead5ac55..1c98de57791 100644 --- a/src/rpc/rawtransaction_util.cpp +++ b/src/rpc/rawtransaction_util.cpp @@ -105,19 +105,23 @@ std::vector> ParseOutputs(const UniValue& out std::set destinations; std::vector> parsed_outputs; bool has_data{false}; - for (const std::string& name_ : outputs.getKeys()) { + const auto& keys{outputs.getKeys()}; + const auto& values{outputs.getValues()}; + for (size_t i{0}; i < keys.size(); ++i) { + const auto& name_{keys[i]}; + const auto& value{values[i]}; if (name_ == "data") { if (has_data) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, duplicate key: data"); } has_data = true; - std::vector data = ParseHexV(outputs[name_].getValStr(), "Data"); + std::vector data = ParseHexV(value.getValStr(), "Data"); CTxDestination destination{CNoDestination{CScript() << OP_RETURN << data}}; CAmount amount{0}; parsed_outputs.emplace_back(destination, amount); } else { CTxDestination destination{DecodeDestination(name_)}; - CAmount amount{AmountFromValue(outputs[name_])}; + CAmount amount{AmountFromValue(value)}; if (!IsValidDestination(destination)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_); }