diff options
-rw-r--r-- | doc/release-notes-28113.md | 7 | ||||
-rw-r--r-- | src/core_io.h | 3 | ||||
-rw-r--r-- | src/core_read.cpp | 36 | ||||
-rw-r--r-- | src/rpc/util.cpp | 18 | ||||
-rw-r--r-- | src/rpc/util.h | 3 | ||||
-rw-r--r-- | src/test/fuzz/parse_univalue.cpp | 2 |
6 files changed, 47 insertions, 22 deletions
diff --git a/doc/release-notes-28113.md b/doc/release-notes-28113.md new file mode 100644 index 0000000000..c1a3a07b17 --- /dev/null +++ b/doc/release-notes-28113.md @@ -0,0 +1,7 @@ +RPC Wallet +---------- + +- The `signrawtransactionwithkey`, `signrawtransactionwithwallet`, + `walletprocesspsbt` and `descriptorprocesspsbt` calls now return more + specific RPC_INVALID_PARAMETER instead of RPC_PARSE_ERROR if their + sighashtype argument is malformed or not a string. diff --git a/src/core_io.h b/src/core_io.h index 997f3bfd5b..a8c62da3f3 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -6,6 +6,7 @@ #define BITCOIN_CORE_IO_H #include <consensus/amount.h> +#include <util/result.h> #include <string> #include <vector> @@ -46,7 +47,7 @@ bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header); */ bool ParseHashStr(const std::string& strHex, uint256& result); std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName); -int ParseSighashString(const UniValue& sighash); +[[nodiscard]] util::Result<int> SighashFromStr(const std::string& sighash); // core_write.cpp UniValue ValueFromAmount(const CAmount amount); diff --git a/src/core_read.cpp b/src/core_read.cpp index 84cd559b7f..c40f04a824 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -11,6 +11,7 @@ #include <serialize.h> #include <streams.h> #include <univalue.h> +#include <util/result.h> #include <util/strencodings.h> #include <version.h> @@ -252,26 +253,21 @@ std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strN return ParseHex(strHex); } -int ParseSighashString(const UniValue& sighash) +util::Result<int> SighashFromStr(const std::string& sighash) { - int hash_type = SIGHASH_DEFAULT; - if (!sighash.isNull()) { - static std::map<std::string, int> map_sighash_values = { - {std::string("DEFAULT"), int(SIGHASH_DEFAULT)}, - {std::string("ALL"), int(SIGHASH_ALL)}, - {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)}, - {std::string("NONE"), int(SIGHASH_NONE)}, - {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)}, - {std::string("SINGLE"), int(SIGHASH_SINGLE)}, - {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)}, - }; - const std::string& strHashType = sighash.get_str(); - const auto& it = map_sighash_values.find(strHashType); - if (it != map_sighash_values.end()) { - hash_type = it->second; - } else { - throw std::runtime_error(strHashType + " is not a valid sighash parameter."); - } + static std::map<std::string, int> map_sighash_values = { + {std::string("DEFAULT"), int(SIGHASH_DEFAULT)}, + {std::string("ALL"), int(SIGHASH_ALL)}, + {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)}, + {std::string("NONE"), int(SIGHASH_NONE)}, + {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)}, + {std::string("SINGLE"), int(SIGHASH_SINGLE)}, + {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)}, + }; + const auto& it = map_sighash_values.find(sighash); + if (it != map_sighash_values.end()) { + return it->second; + } else { + return util::Error{Untranslated(sighash + " is not a valid sighash parameter.")}; } - return hash_type; } diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 19e14f88df..377181dd81 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -3,8 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <clientversion.h> +#include <core_io.h> #include <common/args.h> #include <consensus/amount.h> +#include <script/interpreter.h> #include <key_io.h> #include <outputtype.h> #include <rpc/util.h> @@ -12,6 +14,7 @@ #include <script/signingprovider.h> #include <tinyformat.h> #include <util/check.h> +#include <util/result.h> #include <util/strencodings.h> #include <util/string.h> #include <util/translation.h> @@ -310,6 +313,21 @@ UniValue DescribeAddress(const CTxDestination& dest) return std::visit(DescribeAddressVisitor(), dest); } +int ParseSighashString(const UniValue& sighash) +{ + if (sighash.isNull()) { + return SIGHASH_DEFAULT; + } + if (!sighash.isStr()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "sighash needs to be null or string"); + } + const auto result{SighashFromStr(sighash.get_str())}; + if (!result) { + throw JSONRPCError(RPC_INVALID_PARAMETER, util::ErrorString(result).original); + } + return result.value(); +} + unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target) { const int target{value.getInt<int>()}; diff --git a/src/rpc/util.h b/src/rpc/util.h index 4cba5a9818..02d26f1ab7 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -100,6 +100,9 @@ CTxDestination AddAndGetMultisigDestination(const int required, const std::vecto UniValue DescribeAddress(const CTxDestination& dest); +/** Parse a sighash string representation and raise an RPC error if it is invalid. */ +int ParseSighashString(const UniValue& sighash); + //! Parse a confirm target option and raise an RPC error if it is invalid. unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target); diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp index 6d33c1a8cc..ac3e393401 100644 --- a/src/test/fuzz/parse_univalue.cpp +++ b/src/test/fuzz/parse_univalue.cpp @@ -75,7 +75,7 @@ FUZZ_TARGET_INIT(parse_univalue, initialize_parse_univalue) } try { (void)ParseSighashString(univalue); - } catch (const std::runtime_error&) { + } catch (const UniValue&) { } try { (void)AmountFromValue(univalue); |