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.
This commit is contained in:
Lőrinc
2026-08-19 22:05:42 -07:00
parent 56db08d529
commit 747cff8424

View File

@@ -105,19 +105,23 @@ std::vector<std::pair<CTxDestination, CAmount>> ParseOutputs(const UniValue& out
std::set<CTxDestination> destinations;
std::vector<std::pair<CTxDestination, CAmount>> 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<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");
std::vector<unsigned char> 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_);
}