diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-12-07 17:19:28 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-12-07 17:19:48 +0100 |
commit | d38a2c14168d4c39530ff44cca2d7fec8668045c (patch) | |
tree | be4b575fd92633b51b4861e5bbcbddbf7929f562 /src | |
parent | 2b12268095fa0bc8c62edc7648b365d669a937c2 (diff) | |
parent | fa4c8679ed94f215ce895938f7c3c169a2ce101e (diff) | |
download | bitcoin-d38a2c14168d4c39530ff44cca2d7fec8668045c.tar.xz |
Merge #14890: rpc: Avoid creating non-standard raw transactions
fa4c8679ed94f215ce895938f7c3c169a2ce101e rpc: Avoid creating non-standard raw transactions (MarcoFalke)
Pull request description:
Multiple OP_RETURN outputs in a transaction are not standard and unlikely to be relayed, so avoid creating them.
Apart from that, the logic was broken in that it duplicated the same hex-data for each data output: Closes #14868.
Tree-SHA512: b08d08062b5622e8a7b497e490ccaf53b06e844c863fda3bf3f932a98684a809e8341aeb98232059a795afb32d8770a6c5591a66f8e6ee372b672af245607887
Diffstat (limited to 'src')
-rw-r--r-- | src/rpc/rawtransaction.cpp | 16 | ||||
-rw-r--r-- | src/test/rpc_tests.cpp | 3 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 3 |
3 files changed, 15 insertions, 7 deletions
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index f5f6c344ea..472b65f975 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -397,7 +397,6 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal rawTx.vin.push_back(in); } - std::set<CTxDestination> destinations; if (!outputs_is_obj) { // Translate array of key-value pairs into dict UniValue outputs_dict = UniValue(UniValue::VOBJ); @@ -413,8 +412,17 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal } outputs = std::move(outputs_dict); } + + // Duplicate checking + std::set<CTxDestination> destinations; + bool has_data{false}; + for (const std::string& name_ : outputs.getKeys()) { 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"); CTxOut out(0, CScript() << OP_RETURN << data); @@ -466,7 +474,8 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) }, }, }, - {"outputs", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "a json array with outputs (key-value pairs).\n" + {"outputs", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n" + "That is, each address can only appear once and there can only be one 'data' object.\n" "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n" " accepted as second parameter.", { @@ -1608,7 +1617,8 @@ UniValue createpsbt(const JSONRPCRequest& request) }, }, }, - {"outputs", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "a json array with outputs (key-value pairs).\n" + {"outputs", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n" + "That is, each address can only appear once and there can only be one 'data' object.\n" "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n" " accepted as second parameter.", { diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 121b72a5f7..ff48398925 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -129,9 +129,6 @@ BOOST_AUTO_TEST_CASE(rpc_createraw_op_return) { BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}")); - // Allow more than one data transaction output - BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\",\"data\":\"68656c6c6f776f726c64\"}")); - // Key not "data" (bad address) BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"), std::runtime_error); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4479438238..7d48006606 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4023,7 +4023,8 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request) }, }, }, - {"outputs", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "a json array with outputs (key-value pairs).\n" + {"outputs", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n" + "That is, each address can only appear once and there can only be one 'data' object.\n" "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n" " accepted as second parameter.", { |