Skip to content

Commit d707853

Browse files
committed
Add OP_RETURN support in createrawtransaction RPC call, add tests.
1 parent a4fe57d commit d707853

File tree

2 files changed

+45
-16
lines changed

2 files changed

+45
-16
lines changed

src/rpcrawtransaction.cpp

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,9 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
318318
{
319319
if (fHelp || params.size() != 2)
320320
throw runtime_error(
321-
"createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...}\n"
322-
"\nCreate a transaction spending the given inputs and sending to the given addresses.\n"
321+
"createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...}\n"
322+
"\nCreate a transaction spending the given inputs and creating new outputs.\n"
323+
"Outputs can be addresses or data.\n"
323324
"Returns hex-encoded raw transaction.\n"
324325
"Note that the transaction's inputs are not signed, and\n"
325326
"it is not stored in the wallet or transmitted to the network.\n"
@@ -328,23 +329,25 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
328329
"1. \"transactions\" (string, required) A json array of json objects\n"
329330
" [\n"
330331
" {\n"
331-
" \"txid\":\"id\", (string, required) The transaction id\n"
332+
" \"txid\":\"id\", (string, required) The transaction id\n"
332333
" \"vout\":n (numeric, required) The output number\n"
333334
" }\n"
334335
" ,...\n"
335336
" ]\n"
336-
"2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n"
337+
"2. \"outputs\" (string, required) a json object with outputs\n"
337338
" {\n"
338339
" \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the " + CURRENCY_UNIT + " amount\n"
339-
" ,...\n"
340+
" \"data\": \"hex\", (string, required) The key is \"data\", the value is hex encoded data\n"
341+
" ...\n"
340342
" }\n"
341-
342343
"\nResult:\n"
343344
"\"transaction\" (string) hex string of the transaction\n"
344345

345346
"\nExamples\n"
346347
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"")
348+
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"data\\\":\\\"00010203\\\"}\"")
347349
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
350+
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"")
348351
);
349352

350353
LOCK(cs_main);
@@ -375,19 +378,27 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
375378
set<CBitcoinAddress> setAddress;
376379
vector<string> addrList = sendTo.getKeys();
377380
BOOST_FOREACH(const string& name_, addrList) {
378-
CBitcoinAddress address(name_);
379-
if (!address.IsValid())
380-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
381381

382-
if (setAddress.count(address))
383-
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
384-
setAddress.insert(address);
382+
if (name_ == "data") {
383+
std::vector<unsigned char> data = ParseHexV(sendTo[name_].getValStr(),"Data");
384+
385+
CTxOut out(0, CScript() << OP_RETURN << data);
386+
rawTx.vout.push_back(out);
387+
} else {
388+
CBitcoinAddress address(name_);
389+
if (!address.IsValid())
390+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
385391

386-
CScript scriptPubKey = GetScriptForDestination(address.Get());
387-
CAmount nAmount = AmountFromValue(sendTo[name_]);
392+
if (setAddress.count(address))
393+
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
394+
setAddress.insert(address);
388395

389-
CTxOut out(nAmount, scriptPubKey);
390-
rawTx.vout.push_back(out);
396+
CScript scriptPubKey = GetScriptForDestination(address.Get());
397+
CAmount nAmount = AmountFromValue(sendTo[name_]);
398+
399+
CTxOut out(nAmount, scriptPubKey);
400+
rawTx.vout.push_back(out);
401+
}
391402
}
392403

393404
return EncodeHexTx(rawTx);

src/test/rpc_tests.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,24 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign)
110110
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
111111
}
112112

113+
BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
114+
{
115+
BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}"));
116+
117+
// Allow more than one data transaction output
118+
BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\",\"data\":\"68656c6c6f776f726c64\"}"));
119+
120+
// Key not "data" (bad address)
121+
BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"), runtime_error);
122+
123+
// Bad hex encoding of data output
124+
BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345\"}"), runtime_error);
125+
BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345g\"}"), runtime_error);
126+
127+
// Data 81 bytes long
128+
BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081\"}"));
129+
}
130+
113131
BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
114132
{
115133
BOOST_CHECK(ValueFromAmount(0LL).write() == "0.00000000");

0 commit comments

Comments
 (0)