Browse Source

Add OP_RETURN support in createrawtransaction RPC call, add tests.

0.13
Pavel Janík 10 years ago
parent
commit
d7078533eb
  1. 21
      src/rpcrawtransaction.cpp
  2. 18
      src/test/rpc_tests.cpp

21
src/rpcrawtransaction.cpp

@ -318,8 +318,9 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
{ {
if (fHelp || params.size() != 2) if (fHelp || params.size() != 2)
throw runtime_error( throw runtime_error(
"createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...}\n" "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...}\n"
"\nCreate a transaction spending the given inputs and sending to the given addresses.\n" "\nCreate a transaction spending the given inputs and creating new outputs.\n"
"Outputs can be addresses or data.\n"
"Returns hex-encoded raw transaction.\n" "Returns hex-encoded raw transaction.\n"
"Note that the transaction's inputs are not signed, and\n" "Note that the transaction's inputs are not signed, and\n"
"it is not stored in the wallet or transmitted to the network.\n" "it is not stored in the wallet or transmitted to the network.\n"
@ -333,18 +334,20 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
" }\n" " }\n"
" ,...\n" " ,...\n"
" ]\n" " ]\n"
"2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n" "2. \"outputs\" (string, required) a json object with outputs\n"
" {\n" " {\n"
" \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the " + CURRENCY_UNIT + " amount\n" " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the " + CURRENCY_UNIT + " amount\n"
" ,...\n" " \"data\": \"hex\", (string, required) The key is \"data\", the value is hex encoded data\n"
" ...\n"
" }\n" " }\n"
"\nResult:\n" "\nResult:\n"
"\"transaction\" (string) hex string of the transaction\n" "\"transaction\" (string) hex string of the transaction\n"
"\nExamples\n" "\nExamples\n"
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"") + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"")
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"data\\\":\\\"00010203\\\"}\"")
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"") + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"")
); );
LOCK(cs_main); LOCK(cs_main);
@ -375,6 +378,13 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
set<CBitcoinAddress> setAddress; set<CBitcoinAddress> setAddress;
vector<string> addrList = sendTo.getKeys(); vector<string> addrList = sendTo.getKeys();
BOOST_FOREACH(const string& name_, addrList) { BOOST_FOREACH(const string& name_, addrList) {
if (name_ == "data") {
std::vector<unsigned char> data = ParseHexV(sendTo[name_].getValStr(),"Data");
CTxOut out(0, CScript() << OP_RETURN << data);
rawTx.vout.push_back(out);
} else {
CBitcoinAddress address(name_); CBitcoinAddress address(name_);
if (!address.IsValid()) if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
@ -389,6 +399,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
CTxOut out(nAmount, scriptPubKey); CTxOut out(nAmount, scriptPubKey);
rawTx.vout.push_back(out); rawTx.vout.push_back(out);
} }
}
return EncodeHexTx(rawTx); return EncodeHexTx(rawTx);
} }

18
src/test/rpc_tests.cpp

@ -110,6 +110,24 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign)
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true); BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
} }
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\"}"), runtime_error);
// Bad hex encoding of data output
BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345\"}"), runtime_error);
BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345g\"}"), runtime_error);
// Data 81 bytes long
BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081\"}"));
}
BOOST_AUTO_TEST_CASE(rpc_format_monetary_values) BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
{ {
BOOST_CHECK(ValueFromAmount(0LL).write() == "0.00000000"); BOOST_CHECK(ValueFromAmount(0LL).write() == "0.00000000");

Loading…
Cancel
Save