aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core_io.h2
-rw-r--r--src/core_read.cpp34
-rw-r--r--src/rpc/client.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp16
-rw-r--r--src/test/rpc_tests.cpp4
-rw-r--r--src/wallet/rpcwallet.cpp16
6 files changed, 45 insertions, 29 deletions
diff --git a/src/core_io.h b/src/core_io.h
index 7ed84d6665..3cdae06dfb 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -20,7 +20,7 @@ class UniValue;
// core_read.cpp
CScript ParseScript(const std::string& s);
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
-bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false);
+bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
uint256 ParseHashUV(const UniValue& v, const std::string& strName);
uint256 ParseHashStr(const std::string&, const std::string& strName);
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 2f5b67b5c7..4f2dabe10f 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -108,39 +108,39 @@ bool CheckTxScriptsSanity(const CMutableTransaction& tx)
return true;
}
-bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness)
+bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness, bool try_witness)
{
- if (!IsHex(strHexTx)) {
+ if (!IsHex(hex_tx)) {
return false;
}
- std::vector<unsigned char> txData(ParseHex(strHexTx));
+ std::vector<unsigned char> txData(ParseHex(hex_tx));
- if (fTryNoWitness) {
+ if (try_no_witness) {
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
try {
ssData >> tx;
- if (ssData.eof() && CheckTxScriptsSanity(tx)) {
+ if (ssData.eof() && (!try_witness || CheckTxScriptsSanity(tx))) {
return true;
}
- }
- catch (const std::exception&) {
+ } catch (const std::exception&) {
// Fall through.
}
}
- CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
- try {
- ssData >> tx;
- if (!ssData.empty()) {
- return false;
+ if (try_witness) {
+ CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
+ try {
+ ssData >> tx;
+ if (ssData.empty()) {
+ return true;
+ }
+ } catch (const std::exception&) {
+ // Fall through.
}
}
- catch (const std::exception&) {
- return false;
- }
-
- return true;
+
+ return false;
}
bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index f2fa114313..e641493e1e 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -91,11 +91,13 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "createrawtransaction", 1, "outputs" },
{ "createrawtransaction", 2, "locktime" },
{ "createrawtransaction", 3, "replaceable" },
+ { "decoderawtransaction", 1, "iswitness" },
{ "signrawtransaction", 1, "prevtxs" },
{ "signrawtransaction", 2, "privkeys" },
{ "sendrawtransaction", 1, "allowhighfees" },
{ "combinerawtransaction", 0, "txs" },
{ "fundrawtransaction", 1, "options" },
+ { "fundrawtransaction", 2, "iswitness" },
{ "gettxout", 1, "n" },
{ "gettxout", 2, "include_mempool" },
{ "gettxoutproof", 0, "txids" },
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index fbebdf44d4..1049131d5e 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -441,13 +441,15 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
UniValue decoderawtransaction(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "decoderawtransaction \"hexstring\"\n"
+ "decoderawtransaction \"hexstring\" ( iswitness )\n"
"\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
"\nArguments:\n"
"1. \"hexstring\" (string, required) The transaction hex string\n"
+ "2. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction\n"
+ " If iswitness is not present, heuristic tests will be used in decoding\n"
"\nResult:\n"
"{\n"
@@ -495,12 +497,16 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
);
LOCK(cs_main);
- RPCTypeCheck(request.params, {UniValue::VSTR});
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
CMutableTransaction mtx;
- if (!DecodeHexTx(mtx, request.params[0].get_str(), true))
+ bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();
+ bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool();
+
+ if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ }
UniValue result(UniValue::VOBJ);
TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false);
@@ -1016,7 +1022,7 @@ static const CRPCCommand commands[] =
// --------------------- ------------------------ ----------------------- ----------
{ "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} },
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} },
- { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} },
+ { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} },
{ "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
{ "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees"} },
{ "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 710d09ead6..c69b5f1ca3 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -65,7 +65,9 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "size").get_int(), 193);
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1);
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0);
- BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false"));
+ BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false extra"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("signrawtransaction"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), std::runtime_error);
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 4da56fbe8a..f839a18612 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2982,9 +2982,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "fundrawtransaction \"hexstring\" ( options )\n"
+ "fundrawtransaction \"hexstring\" ( options iswitness )\n"
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
"This will not modify existing inputs, and will add at most one change output to the outputs.\n"
"No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
@@ -3019,6 +3019,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" \"CONSERVATIVE\"\n"
" }\n"
" for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
+ "3. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction \n"
+ " If iswitness is not present, heuristic tests will be used in decoding\n"
+
"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
@@ -3055,7 +3058,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
coinControl.fAllowWatchOnly = request.params[1].get_bool();
}
else {
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ, UniValue::VBOOL});
UniValue options = request.params[1];
@@ -3124,8 +3127,11 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
// parse hex string from parameter
CMutableTransaction tx;
- if (!DecodeHexTx(tx, request.params[0].get_str(), true))
+ bool try_witness = request.params[2].isNull() ? true : request.params[2].get_bool();
+ bool try_no_witness = request.params[2].isNull() ? true : !request.params[2].get_bool();
+ if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ }
if (tx.vout.size() == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
@@ -3443,7 +3449,7 @@ extern UniValue rescanblockchain(const JSONRPCRequest& request);
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
- { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options"} },
+ { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },
{ "hidden", "resendwallettransactions", &resendwallettransactions, {} },
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
{ "wallet", "abortrescan", &abortrescan, {} },