0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-10 10:52:31 -05:00

refactor: move parsing to new function

Move the parsing and validation out of `AddOutputs` into its own function,
`ParseOutputs`. This allows us to re-use this logic in `ParseRecipients` in a
later commit, where the code is currently duplicated.

The new `ParseOutputs` function returns a CTxDestination,CAmount tuples.
This allows the caller to then translate the validated outputs into
either CRecipients or CTxOuts.
This commit is contained in:
josibake 2023-12-22 11:27:53 +01:00
parent 6f569ac903
commit f7384b921c
No known key found for this signature in database
GPG key ID: 8ADCB558C4F33D65
2 changed files with 28 additions and 16 deletions

View file

@ -97,15 +97,12 @@ UniValue NormalizeOutputs(const UniValue& outputs_in)
return outputs; return outputs;
} }
void AddOutputs(CMutableTransaction& rawTx, const UniValue& outputs_in) std::vector<std::pair<CTxDestination, CAmount>> ParseOutputs(const UniValue& outputs)
{ {
UniValue outputs(UniValue::VOBJ);
outputs = NormalizeOutputs(outputs_in);
// Duplicate checking // Duplicate checking
std::set<CTxDestination> destinations; std::set<CTxDestination> destinations;
std::vector<std::pair<CTxDestination, CAmount>> parsed_outputs;
bool has_data{false}; bool has_data{false};
for (const std::string& name_ : outputs.getKeys()) { for (const std::string& name_ : outputs.getKeys()) {
if (name_ == "data") { if (name_ == "data") {
if (has_data) { if (has_data) {
@ -113,11 +110,12 @@ void AddOutputs(CMutableTransaction& rawTx, const UniValue& outputs_in)
} }
has_data = true; has_data = true;
std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data"); std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");
CTxDestination destination{CNoDestination{CScript() << OP_RETURN << data}};
CTxOut out(0, CScript() << OP_RETURN << data); CAmount amount{0};
rawTx.vout.push_back(out); parsed_outputs.emplace_back(destination, amount);
} else { } else {
CTxDestination destination = DecodeDestination(name_); CTxDestination destination{DecodeDestination(name_)};
CAmount amount{AmountFromValue(outputs[name_])};
if (!IsValidDestination(destination)) { if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
} }
@ -125,14 +123,24 @@ void AddOutputs(CMutableTransaction& rawTx, const UniValue& outputs_in)
if (!destinations.insert(destination).second) { if (!destinations.insert(destination).second) {
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_); throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
} }
parsed_outputs.emplace_back(destination, amount);
CScript scriptPubKey = GetScriptForDestination(destination);
CAmount nAmount = AmountFromValue(outputs[name_]);
CTxOut out(nAmount, scriptPubKey);
rawTx.vout.push_back(out);
} }
} }
return parsed_outputs;
}
void AddOutputs(CMutableTransaction& rawTx, const UniValue& outputs_in)
{
UniValue outputs(UniValue::VOBJ);
outputs = NormalizeOutputs(outputs_in);
std::vector<std::pair<CTxDestination, CAmount>> parsed_outputs = ParseOutputs(outputs);
for (const auto& [destination, nAmount] : parsed_outputs) {
CScript scriptPubKey = GetScriptForDestination(destination);
CTxOut out(nAmount, scriptPubKey);
rawTx.vout.push_back(out);
}
} }
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, std::optional<bool> rbf) CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, std::optional<bool> rbf)

View file

@ -5,6 +5,8 @@
#ifndef BITCOIN_RPC_RAWTRANSACTION_UTIL_H #ifndef BITCOIN_RPC_RAWTRANSACTION_UTIL_H
#define BITCOIN_RPC_RAWTRANSACTION_UTIL_H #define BITCOIN_RPC_RAWTRANSACTION_UTIL_H
#include <addresstype.h>
#include <consensus/amount.h>
#include <map> #include <map>
#include <string> #include <string>
#include <optional> #include <optional>
@ -38,13 +40,15 @@ void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const
*/ */
void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins); void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins);
/** Normalize univalue-represented inputs and add them to the transaction */ /** Normalize univalue-represented inputs and add them to the transaction */
void AddInputs(CMutableTransaction& rawTx, const UniValue& inputs_in, bool rbf); void AddInputs(CMutableTransaction& rawTx, const UniValue& inputs_in, bool rbf);
/** Normalize univalue-represented outputs */ /** Normalize univalue-represented outputs */
UniValue NormalizeOutputs(const UniValue& outputs_in); UniValue NormalizeOutputs(const UniValue& outputs_in);
/** Parse normalized outputs into destination, amount tuples */
std::vector<std::pair<CTxDestination, CAmount>> ParseOutputs(const UniValue& outputs);
/** Normalize, parse, and add outputs to the transaction */ /** Normalize, parse, and add outputs to the transaction */
void AddOutputs(CMutableTransaction& rawTx, const UniValue& outputs_in); void AddOutputs(CMutableTransaction& rawTx, const UniValue& outputs_in);