Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/rawtransaction.cpp
Show First 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | for (const CTxDestination &addr : addresses) { | ||||
a.push_back(EncodeDestination(addr)); | a.push_back(EncodeDestination(addr)); | ||||
} | } | ||||
out.push_back(Pair("addresses", a)); | out.push_back(Pair("addresses", a)); | ||||
} | } | ||||
void TxToJSON(const CTransaction &tx, const uint256 hashBlock, | void TxToJSON(const CTransaction &tx, const uint256 hashBlock, | ||||
UniValue &entry) { | UniValue &entry) { | ||||
entry.push_back(Pair("txid", tx.GetId().GetHex())); | entry.push_back(Pair("unspentid", tx.Getunspentid().GetHex())); | ||||
entry.push_back(Pair("hash", tx.GetHash().GetHex())); | entry.push_back(Pair("hash", tx.GetHash().GetHex())); | ||||
entry.push_back(Pair( | entry.push_back(Pair( | ||||
"size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION))); | "size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION))); | ||||
entry.push_back(Pair("version", tx.nVersion)); | entry.push_back(Pair("version", tx.nVersion)); | ||||
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); | entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); | ||||
UniValue vin(UniValue::VARR); | UniValue vin(UniValue::VARR); | ||||
for (unsigned int i = 0; i < tx.vin.size(); i++) { | for (unsigned int i = 0; i < tx.vin.size(); i++) { | ||||
const CTxIn &txin = tx.vin[i]; | const CTxIn &txin = tx.vin[i]; | ||||
UniValue in(UniValue::VOBJ); | UniValue in(UniValue::VOBJ); | ||||
if (tx.IsCoinBase()) { | if (tx.IsCoinBase()) { | ||||
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), | in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), | ||||
txin.scriptSig.end()))); | txin.scriptSig.end()))); | ||||
} else { | } else { | ||||
in.push_back(Pair("txid", txin.prevout.hash.GetHex())); | in.push_back(Pair("unspentid", txin.prevout.unspentid.GetHex())); | ||||
in.push_back(Pair("vout", (int64_t)txin.prevout.n)); | in.push_back(Pair("vout", (int64_t)txin.prevout.n)); | ||||
UniValue o(UniValue::VOBJ); | UniValue o(UniValue::VOBJ); | ||||
o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true))); | o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true))); | ||||
o.push_back(Pair( | o.push_back(Pair( | ||||
"hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); | "hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); | ||||
in.push_back(Pair("scriptSig", o)); | in.push_back(Pair("scriptSig", o)); | ||||
} | } | ||||
Show All 33 Lines | void TxToJSON(const CTransaction &tx, const uint256 hashBlock, | ||||
} | } | ||||
} | } | ||||
static UniValue getrawtransaction(const Config &config, | static UniValue getrawtransaction(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | if (request.fHelp || request.params.size() < 1 || | ||||
request.params.size() > 2) { | request.params.size() > 2) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"getrawtransaction \"txid\" ( verbose )\n" | "getrawtransaction \"txhash\" ( verbose )\n" | ||||
"\nNOTE: By default this function only works for mempool " | "\nNOTE: By default this function only works for mempool " | ||||
"transactions. If the -txindex option is\n" | "transactions. If the -txindex option is\n" | ||||
"enabled, it also works for blockchain transactions.\n" | "enabled, it also works for blockchain transactions.\n" | ||||
"DEPRECATED: for now, it also works for transactions with unspent " | |||||
"outputs.\n" | |||||
"\nReturn the raw transaction data.\n" | "\nReturn the raw transaction data.\n" | ||||
"\nIf verbose is 'true', returns an Object with information about " | "\nIf verbose is 'true', returns an Object with information about " | ||||
"'txid'.\n" | "'txhash'.\n" | ||||
"If verbose is 'false' or omitted, returns a string that is " | "If verbose is 'false' or omitted, returns a string that is " | ||||
"serialized, hex-encoded data for 'txid'.\n" | "serialized, hex-encoded data for 'txhash'.\n" | ||||
"\nArguments:\n" | "\nArguments:\n" | ||||
"1. \"txid\" (string, required) The transaction id\n" | "1. \"txhash\" (string, required) The transaction id\n" | ||||
"2. verbose (bool, optional, default=false) If false, return " | "2. verbose (bool, optional, default=false) If false, return " | ||||
"a string, otherwise return a json object\n" | "a string, otherwise return a json object\n" | ||||
"\nResult (if verbose is not set or set to false):\n" | "\nResult (if verbose is not set or set to false):\n" | ||||
"\"data\" (string) The serialized, hex-encoded data for " | "\"data\" (string) The serialized, hex-encoded data for " | ||||
"'txid'\n" | "'txhash'\n" | ||||
"\nResult (if verbose is set to true):\n" | "\nResult (if verbose is set to true):\n" | ||||
"{\n" | "{\n" | ||||
" \"hex\" : \"data\", (string) The serialized, hex-encoded " | " \"hex\" : \"data\", (string) The serialized, hex-encoded " | ||||
"data for 'txid'\n" | "data for 'txhash'\n" | ||||
" \"txid\" : \"id\", (string) The transaction id (same as " | " \"txhash\" : \"id\", (string) The transaction hash (same " | ||||
"as " | |||||
"provided)\n" | "provided)\n" | ||||
" \"hash\" : \"id\", (string) The transaction hash " | |||||
"(differs from txid for witness transactions)\n" | |||||
" \"size\" : n, (numeric) The serialized transaction " | " \"size\" : n, (numeric) The serialized transaction " | ||||
"size\n" | "size\n" | ||||
" \"version\" : n, (numeric) The version\n" | " \"version\" : n, (numeric) The version\n" | ||||
" \"locktime\" : ttt, (numeric) The lock time\n" | " \"locktime\" : ttt, (numeric) The lock time\n" | ||||
" \"vin\" : [ (array of json objects)\n" | " \"vin\" : [ (array of json objects)\n" | ||||
" {\n" | " {\n" | ||||
" \"txid\": \"id\", (string) The transaction id\n" | " \"unspentid\": \"id\", (string) The transaction id\n" | ||||
" \"vout\": n, (numeric) \n" | " \"vout\": n, (numeric) \n" | ||||
" \"scriptSig\": { (json object) The script\n" | " \"scriptSig\": { (json object) The script\n" | ||||
" \"asm\": \"asm\", (string) asm\n" | " \"asm\": \"asm\", (string) asm\n" | ||||
" \"hex\": \"hex\" (string) hex\n" | " \"hex\": \"hex\" (string) hex\n" | ||||
" },\n" | " },\n" | ||||
" \"sequence\": n (numeric) The script sequence number\n" | " \"sequence\": n (numeric) The script sequence number\n" | ||||
" }\n" | " }\n" | ||||
" ,...\n" | " ,...\n" | ||||
Show All 22 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
" \"confirmations\" : n, (numeric) The confirmations\n" | " \"confirmations\" : n, (numeric) The confirmations\n" | ||||
" \"time\" : ttt, (numeric) The transaction time in " | " \"time\" : ttt, (numeric) The transaction time in " | ||||
"seconds since epoch (Jan 1 1970 GMT)\n" | "seconds since epoch (Jan 1 1970 GMT)\n" | ||||
" \"blocktime\" : ttt (numeric) The block time in seconds " | " \"blocktime\" : ttt (numeric) The block time in seconds " | ||||
"since epoch (Jan 1 1970 GMT)\n" | "since epoch (Jan 1 1970 GMT)\n" | ||||
"}\n" | "}\n" | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("getrawtransaction", "\"mytxid\"") + | HelpExampleCli("getrawtransaction", "\"mytxhash\"") + | ||||
HelpExampleCli("getrawtransaction", "\"mytxid\" true") + | HelpExampleCli("getrawtransaction", "\"mytxhash\" true") + | ||||
HelpExampleRpc("getrawtransaction", "\"mytxid\", true")); | HelpExampleRpc("getrawtransaction", "\"mytxhash\", true")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
uint256 hash = ParseHashV(request.params[0], "parameter 1"); | txhash_t hash = txhash_t(ParseHashV(request.params[0], "parameter 1")); | ||||
// Accept either a bool (true) or a num (>=1) to indicate verbose output. | // Accept either a bool (true) or a num (>=1) to indicate verbose output. | ||||
bool fVerbose = false; | bool fVerbose = false; | ||||
if (request.params.size() > 1) { | if (request.params.size() > 1) { | ||||
if (request.params[1].isNum()) { | if (request.params[1].isNum()) { | ||||
if (request.params[1].get_int() != 0) { | if (request.params[1].get_int() != 0) { | ||||
fVerbose = true; | fVerbose = true; | ||||
} | } | ||||
Show All 31 Lines | static UniValue getrawtransaction(const Config &config, | ||||
return result; | return result; | ||||
} | } | ||||
static UniValue gettxoutproof(const Config &config, | static UniValue gettxoutproof(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || | if (request.fHelp || | ||||
(request.params.size() != 1 && request.params.size() != 2)) { | (request.params.size() != 1 && request.params.size() != 2)) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"gettxoutproof [\"txid\",...] ( blockhash )\n" | "gettxoutproof [\"txhash\",...] ( blockhash )\n" | ||||
"\nReturns a hex-encoded proof that \"txid\" was included in a " | "\nReturns a hex-encoded proof that \"txhash\" was included in a " | ||||
"block.\n" | "block.\n" | ||||
"\nNOTE: This function only works if a transaction index is " | "\nNOTE: This function only works if a transaction index is " | ||||
"maintained using the\n" | "maintained using the\n" | ||||
"-txindex command line option or by specifying the block in " | "-txindex command line option or by specifying the block in " | ||||
"which the transaction\n" | "which the transaction\n" | ||||
"is included manually (by blockhash).\n" | "is included manually (by blockhash).\n" | ||||
"\nArguments:\n" | "\nArguments:\n" | ||||
"1. \"txids\" (string) A json array of txids to filter\n" | "1. \"txhashes\" (string) A json array of txhashes to " | ||||
"filter\n" | |||||
" [\n" | " [\n" | ||||
" \"txid\" (string) A transaction hash\n" | " \"txhash\" (string) A transaction hash\n" | ||||
" ,...\n" | " ,...\n" | ||||
" ]\n" | " ]\n" | ||||
"2. \"blockhash\" (string, optional) If specified, looks for " | "2. \"blockhash\" (string, optional) If specified, looks for " | ||||
"txid in the block with this hash\n" | "txhash in the block with this hash\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"\"data\" (string) A string that is a serialized, " | "\"data\" (string) A string that is a serialized, " | ||||
"hex-encoded data for the proof.\n"); | "hex-encoded data for the proof.\n"); | ||||
} | } | ||||
std::set<uint256> setTxids; | std::set<txhash_t> setTxhashes; | ||||
uint256 oneTxid; | txhash_t oneTxhash; | ||||
UniValue txids = request.params[0].get_array(); | UniValue txhashes = request.params[0].get_array(); | ||||
for (unsigned int idx = 0; idx < txids.size(); idx++) { | for (unsigned int idx = 0; idx < txhashes.size(); idx++) { | ||||
const UniValue &txid = txids[idx]; | const UniValue &txhash = txhashes[idx]; | ||||
if (txid.get_str().length() != 64 || !IsHex(txid.get_str())) { | if (txhash.get_str().length() != 64 || !IsHex(txhash.get_str())) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
std::string("Invalid txid ") + txid.get_str()); | std::string("Invalid txhash ") + | ||||
txhash.get_str()); | |||||
} | } | ||||
uint256 hash(uint256S(txid.get_str())); | txhash_t hash(uint256S(txhash.get_str())); | ||||
if (setTxids.count(hash)) { | if (setTxhashes.count(hash)) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
std::string("Invalid parameter, duplicated txid: ") + | std::string("Invalid parameter, duplicated txhash: ") + | ||||
txid.get_str()); | txhash.get_str()); | ||||
} | } | ||||
setTxids.insert(hash); | setTxhashes.insert(hash); | ||||
oneTxid = hash; | oneTxhash = hash; | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pblockindex = nullptr; | CBlockIndex *pblockindex = nullptr; | ||||
uint256 hashBlock; | uint256 hashBlock; | ||||
if (request.params.size() > 1) { | if (request.params.size() > 1) { | ||||
hashBlock = uint256S(request.params[1].get_str()); | hashBlock = uint256S(request.params[1].get_str()); | ||||
if (!mapBlockIndex.count(hashBlock)) | if (!mapBlockIndex.count(hashBlock)) | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
pblockindex = mapBlockIndex[hashBlock]; | pblockindex = mapBlockIndex[hashBlock]; | ||||
} | } | ||||
if (pblockindex == nullptr) { | if (pblockindex == nullptr) { | ||||
if (!fTxIndex) { | if (!fTxIndex) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Missing blockhash parameter."); | "Missing blockhash parameter."); | ||||
} | } | ||||
CTransactionRef tx; | CTransactionRef tx; | ||||
if (!GetTransaction(config, oneTxid, tx, hashBlock) || | if (!GetTransaction(config, oneTxhash, tx, hashBlock) || | ||||
hashBlock.IsNull()) { | hashBlock.IsNull()) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Transaction not yet in block"); | "Transaction not yet in block"); | ||||
} | } | ||||
if (!mapBlockIndex.count(hashBlock)) { | if (!mapBlockIndex.count(hashBlock)) { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt"); | throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt"); | ||||
} | } | ||||
pblockindex = mapBlockIndex[hashBlock]; | pblockindex = mapBlockIndex[hashBlock]; | ||||
} | } | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) { | if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); | throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); | ||||
} | } | ||||
unsigned int ntxFound = 0; | unsigned int ntxFound = 0; | ||||
for (const auto &tx : block.vtx) { | for (const auto &tx : block.vtx) { | ||||
if (setTxids.count(tx->GetId())) { | if (setTxhashes.count(tx->GetHash())) { | ||||
ntxFound++; | ntxFound++; | ||||
} | } | ||||
} | } | ||||
if (ntxFound != setTxids.size()) { | if (ntxFound != setTxhashes.size()) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_ADDRESS_OR_KEY, | RPC_INVALID_ADDRESS_OR_KEY, | ||||
"(Not all) transactions not found in specified block"); | "(Not all) transactions not found in specified block"); | ||||
} | } | ||||
CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); | CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); | ||||
CMerkleBlock mb(block, setTxids); | CMerkleBlock mb(block, setTxhashes); | ||||
ssMB << mb; | ssMB << mb; | ||||
std::string strHex = HexStr(ssMB.begin(), ssMB.end()); | std::string strHex = HexStr(ssMB.begin(), ssMB.end()); | ||||
return strHex; | return strHex; | ||||
} | } | ||||
static UniValue verifytxoutproof(const Config &config, | static UniValue verifytxoutproof(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | if (request.fHelp || request.params.size() != 1) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"verifytxoutproof \"proof\"\n" | "verifytxoutproof \"proof\"\n" | ||||
"\nVerifies that a proof points to a transaction in a block, " | "\nVerifies that a proof points to a transaction in a block, " | ||||
"returning the transaction it commits to\n" | "returning the transaction it commits to\n" | ||||
"and throwing an RPC error if the block is not in our best chain\n" | "and throwing an RPC error if the block is not in our best chain\n" | ||||
"\nArguments:\n" | "\nArguments:\n" | ||||
"1. \"proof\" (string, required) The hex-encoded proof " | "1. \"proof\" (string, required) The hex-encoded proof " | ||||
"generated by gettxoutproof\n" | "generated by gettxoutproof\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"[\"txid\"] (array, strings) The txid(s) which the proof " | "[\"txhash\"] (array, strings) The txhashes which the proof " | ||||
"commits to, or empty array if the proof is invalid\n"); | "commits to, or empty array if the proof is invalid\n"); | ||||
} | } | ||||
CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, | CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, | ||||
PROTOCOL_VERSION); | PROTOCOL_VERSION); | ||||
CMerkleBlock merkleBlock; | CMerkleBlock merkleBlock; | ||||
ssMB >> merkleBlock; | ssMB >> merkleBlock; | ||||
Show All 21 Lines | static UniValue verifytxoutproof(const Config &config, | ||||
return res; | return res; | ||||
} | } | ||||
static UniValue createrawtransaction(const Config &config, | static UniValue createrawtransaction(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 2 || | if (request.fHelp || request.params.size() < 2 || | ||||
request.params.size() > 3) { | request.params.size() > 3) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] " | "createrawtransaction [{\"unspentid\":\"id\",\"vout\":n},...] " | ||||
"{\"address\":amount,\"data\":\"hex\",...} ( locktime )\n" | "{\"address\":amount,\"data\":\"hex\",...} ( locktime )\n" | ||||
"\nCreate a transaction spending the given inputs and creating new " | "\nCreate a transaction spending the given inputs and creating new " | ||||
"outputs.\n" | "outputs.\n" | ||||
"Outputs can be addresses or data.\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" | ||||
"\nArguments:\n" | "\nArguments:\n" | ||||
"1. \"inputs\" (array, required) A json array of " | "1. \"inputs\" (array, required) A json array of " | ||||
"json objects\n" | "json objects\n" | ||||
" [\n" | " [\n" | ||||
" {\n" | " {\n" | ||||
" \"txid\":\"id\", (string, required) The transaction " | " \"unspentid\":\"id\", (string, required) The unspent " | ||||
"transaction " | |||||
"id\n" | "id\n" | ||||
" \"vout\":n, (numeric, required) The output " | " \"vout\":n, (numeric, required) The output " | ||||
"number\n" | "number\n" | ||||
" \"sequence\":n (numeric, optional) The sequence " | " \"sequence\":n (numeric, optional) The sequence " | ||||
"number\n" | "number\n" | ||||
" } \n" | " } \n" | ||||
" ,...\n" | " ,...\n" | ||||
" ]\n" | " ]\n" | ||||
Show All 11 Lines | if (request.fHelp || request.params.size() < 2 || | ||||
" }\n" | " }\n" | ||||
"3. locktime (numeric, optional, default=0) Raw " | "3. locktime (numeric, optional, default=0) Raw " | ||||
"locktime. Non-0 value also locktime-activates inputs\n" | "locktime. Non-0 value also locktime-activates inputs\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"\"transaction\" (string) hex string of the " | "\"transaction\" (string) hex string of the " | ||||
"transaction\n" | "transaction\n" | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("createrawtransaction", | HelpExampleCli( | ||||
"\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" " | "createrawtransaction", | ||||
"\"[{\\\"unspentid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" " | |||||
"\"{\\\"address\\\":0.01}\"") + | "\"{\\\"address\\\":0.01}\"") + | ||||
HelpExampleCli("createrawtransaction", | HelpExampleCli( | ||||
"\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" " | "createrawtransaction", | ||||
"\"[{\\\"unspentid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" " | |||||
"\"{\\\"data\\\":\\\"00010203\\\"}\"") + | "\"{\\\"data\\\":\\\"00010203\\\"}\"") + | ||||
HelpExampleRpc("createrawtransaction", | HelpExampleRpc( | ||||
"\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", " | "createrawtransaction", | ||||
"\"[{\\\"unspentid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", " | |||||
"\"{\\\"address\\\":0.01}\"") + | "\"{\\\"address\\\":0.01}\"") + | ||||
HelpExampleRpc("createrawtransaction", | HelpExampleRpc( | ||||
"\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", " | "createrawtransaction", | ||||
"\"[{\\\"unspentid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", " | |||||
"\"{\\\"data\\\":\\\"00010203\\\"}\"")); | "\"{\\\"data\\\":\\\"00010203\\\"}\"")); | ||||
} | } | ||||
RPCTypeCheck(request.params, | RPCTypeCheck(request.params, | ||||
{UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true); | {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true); | ||||
if (request.params[0].isNull() || request.params[1].isNull()) { | if (request.params[0].isNull() || request.params[1].isNull()) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
"Invalid parameter, arguments 1 and 2 must be non-null"); | "Invalid parameter, arguments 1 and 2 must be non-null"); | ||||
Show All 13 Lines | if (request.params.size() > 2 && !request.params[2].isNull()) { | ||||
rawTx.nLockTime = nLockTime; | rawTx.nLockTime = nLockTime; | ||||
} | } | ||||
for (size_t idx = 0; idx < inputs.size(); idx++) { | for (size_t idx = 0; idx < inputs.size(); idx++) { | ||||
const UniValue &input = inputs[idx]; | const UniValue &input = inputs[idx]; | ||||
const UniValue &o = input.get_obj(); | const UniValue &o = input.get_obj(); | ||||
uint256 txid = ParseHashO(o, "txid"); | unspentid_t unspentid = unspentid_t(ParseHashO(o, "unspentid")); | ||||
const UniValue &vout_v = find_value(o, "vout"); | const UniValue &vout_v = find_value(o, "vout"); | ||||
if (!vout_v.isNum()) { | if (!vout_v.isNum()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Invalid parameter, missing vout key"); | "Invalid parameter, missing vout key"); | ||||
} | } | ||||
int nOutput = vout_v.get_int(); | int nOutput = vout_v.get_int(); | ||||
Show All 14 Lines | for (size_t idx = 0; idx < inputs.size(); idx++) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
"Invalid parameter, sequence number is out of range"); | "Invalid parameter, sequence number is out of range"); | ||||
} | } | ||||
nSequence = uint32_t(seqNr64); | nSequence = uint32_t(seqNr64); | ||||
} | } | ||||
CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence); | CTxIn in(COutPoint(unspentid, nOutput), CScript(), nSequence); | ||||
rawTx.vin.push_back(in); | rawTx.vin.push_back(in); | ||||
} | } | ||||
std::set<CTxDestination> destinations; | std::set<CTxDestination> destinations; | ||||
std::vector<std::string> addrList = sendTo.getKeys(); | std::vector<std::string> addrList = sendTo.getKeys(); | ||||
for (const std::string &name_ : addrList) { | for (const std::string &name_ : addrList) { | ||||
if (name_ == "data") { | if (name_ == "data") { | ||||
std::vector<uint8_t> data = | std::vector<uint8_t> data = | ||||
Show All 36 Lines | if (request.fHelp || request.params.size() != 1) { | ||||
"transaction.\n" | "transaction.\n" | ||||
"\nArguments:\n" | "\nArguments:\n" | ||||
"1. \"hexstring\" (string, required) The transaction hex " | "1. \"hexstring\" (string, required) The transaction hex " | ||||
"string\n" | "string\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"{\n" | "{\n" | ||||
" \"txid\" : \"id\", (string) The transaction id\n" | " \"unspentid\" : \"id\", (string) The transaction id\n" | ||||
" \"hash\" : \"id\", (string) The transaction hash " | " \"hash\" : \"id\", (string) The transaction hash " | ||||
"(differs from txid for witness transactions)\n" | |||||
" \"size\" : n, (numeric) The transaction size\n" | " \"size\" : n, (numeric) The transaction size\n" | ||||
" \"version\" : n, (numeric) The version\n" | " \"version\" : n, (numeric) The version\n" | ||||
" \"locktime\" : ttt, (numeric) The lock time\n" | " \"locktime\" : ttt, (numeric) The lock time\n" | ||||
" \"vin\" : [ (array of json objects)\n" | " \"vin\" : [ (array of json objects)\n" | ||||
" {\n" | " {\n" | ||||
" \"txid\": \"id\", (string) The transaction id\n" | " \"unspentid\": \"id\", (string) The transaction id\n" | ||||
" \"vout\": n, (numeric) The output number\n" | " \"vout\": n, (numeric) The output number\n" | ||||
" \"scriptSig\": { (json object) The script\n" | " \"scriptSig\": { (json object) The script\n" | ||||
" \"asm\": \"asm\", (string) asm\n" | " \"asm\": \"asm\", (string) asm\n" | ||||
" \"hex\": \"hex\" (string) hex\n" | " \"hex\": \"hex\" (string) hex\n" | ||||
" },\n" | " },\n" | ||||
" \"sequence\": n (numeric) The script sequence number\n" | " \"sequence\": n (numeric) The script sequence number\n" | ||||
" }\n" | " }\n" | ||||
" ,...\n" | " ,...\n" | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/** | /** | ||||
* Pushes a JSON object for script verification or signing errors to vErrorsRet. | * Pushes a JSON object for script verification or signing errors to vErrorsRet. | ||||
*/ | */ | ||||
static void TxInErrorToJSON(const CTxIn &txin, UniValue &vErrorsRet, | static void TxInErrorToJSON(const CTxIn &txin, UniValue &vErrorsRet, | ||||
const std::string &strMessage) { | const std::string &strMessage) { | ||||
UniValue entry(UniValue::VOBJ); | UniValue entry(UniValue::VOBJ); | ||||
entry.push_back(Pair("txid", txin.prevout.hash.ToString())); | entry.push_back(Pair("unspentid", txin.prevout.unspentid.ToString())); | ||||
entry.push_back(Pair("vout", (uint64_t)txin.prevout.n)); | entry.push_back(Pair("vout", (uint64_t)txin.prevout.n)); | ||||
entry.push_back(Pair("scriptSig", | entry.push_back(Pair("scriptSig", | ||||
HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); | HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); | ||||
entry.push_back(Pair("sequence", (uint64_t)txin.nSequence)); | entry.push_back(Pair("sequence", (uint64_t)txin.nSequence)); | ||||
entry.push_back(Pair("error", strMessage)); | entry.push_back(Pair("error", strMessage)); | ||||
vErrorsRet.push_back(entry); | vErrorsRet.push_back(entry); | ||||
} | } | ||||
static UniValue signrawtransaction(const Config &config, | static UniValue signrawtransaction(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | if (request.fHelp || request.params.size() < 1 || | ||||
request.params.size() > 4) { | request.params.size() > 4) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"signrawtransaction \"hexstring\" ( " | "signrawtransaction \"hexstring\" ( " | ||||
"[{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\"," | "[{\"unspentid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\"," | ||||
"\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype " | "\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype " | ||||
")\n" | ")\n" | ||||
"\nSign inputs for raw transaction (serialized, hex-encoded).\n" | "\nSign inputs for raw transaction (serialized, hex-encoded).\n" | ||||
"The second optional argument (may be null) is an array of " | "The second optional argument (may be null) is an array of " | ||||
"previous transaction outputs that\n" | "previous transaction outputs that\n" | ||||
"this transaction depends on but may not yet be in the block " | "this transaction depends on but may not yet be in the block " | ||||
"chain.\n" | "chain.\n" | ||||
"The third optional argument (may be null) is an array of " | "The third optional argument (may be null) is an array of " | ||||
"base58-encoded private\n" | "base58-encoded private\n" | ||||
"keys that, if given, will be the only keys used to sign the " | "keys that, if given, will be the only keys used to sign the " | ||||
"transaction.\n" | "transaction.\n" | ||||
#ifdef ENABLE_WALLET | #ifdef ENABLE_WALLET | ||||
+ HelpRequiringPassphrase() + | + HelpRequiringPassphrase() + | ||||
"\n" | "\n" | ||||
#endif | #endif | ||||
"\nArguments:\n" | "\nArguments:\n" | ||||
"1. \"hexstring\" (string, required) The transaction hex " | "1. \"hexstring\" (string, required) The transaction hex " | ||||
"string\n" | "string\n" | ||||
"2. \"prevtxs\" (string, optional) An json array of previous " | "2. \"prevtxs\" (string, optional) An json array of previous " | ||||
"dependent transaction outputs\n" | "dependent transaction outputs\n" | ||||
" [ (json array of json objects, or 'null' if " | " [ (json array of json objects, or 'null' if " | ||||
"none provided)\n" | "none provided)\n" | ||||
" {\n" | " {\n" | ||||
" \"txid\":\"id\", (string, required) The " | " \"unspentid\":\"id\", (string, required) The " | ||||
"transaction id\n" | "transaction id\n" | ||||
" \"vout\":n, (numeric, required) The " | " \"vout\":n, (numeric, required) The " | ||||
"output number\n" | "output number\n" | ||||
" \"scriptPubKey\": \"hex\", (string, required) script " | " \"scriptPubKey\": \"hex\", (string, required) script " | ||||
"key\n" | "key\n" | ||||
" \"redeemScript\": \"hex\", (string, required for P2SH " | " \"redeemScript\": \"hex\", (string, required for P2SH " | ||||
"or P2WSH) redeem script\n" | "or P2WSH) redeem script\n" | ||||
" \"amount\": value (numeric, required) The " | " \"amount\": value (numeric, required) The " | ||||
Show All 27 Lines | #endif | ||||
"{\n" | "{\n" | ||||
" \"hex\" : \"value\", (string) The hex-encoded raw " | " \"hex\" : \"value\", (string) The hex-encoded raw " | ||||
"transaction with signature(s)\n" | "transaction with signature(s)\n" | ||||
" \"complete\" : true|false, (boolean) If the transaction has a " | " \"complete\" : true|false, (boolean) If the transaction has a " | ||||
"complete set of signatures\n" | "complete set of signatures\n" | ||||
" \"errors\" : [ (json array of objects) Script " | " \"errors\" : [ (json array of objects) Script " | ||||
"verification errors (if there are any)\n" | "verification errors (if there are any)\n" | ||||
" {\n" | " {\n" | ||||
" \"txid\" : \"hash\", (string) The hash of the " | " \"unspentid\" : \"unspentid\", (string) The hash of the " | ||||
"referenced, previous transaction\n" | "referenced, previous transaction\n" | ||||
" \"vout\" : n, (numeric) The index of the " | " \"vout\" : n, (numeric) The index of the " | ||||
"output to spent and used as input\n" | "output to spent and used as input\n" | ||||
" \"scriptSig\" : \"hex\", (string) The hex-encoded " | " \"scriptSig\" : \"hex\", (string) The hex-encoded " | ||||
"signature script\n" | "signature script\n" | ||||
" \"sequence\" : n, (numeric) Script sequence " | " \"sequence\" : n, (numeric) Script sequence " | ||||
"number\n" | "number\n" | ||||
" \"error\" : \"text\" (string) Verification or " | " \"error\" : \"text\" (string) Verification or " | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
// Add previous txouts given in the RPC call: | // Add previous txouts given in the RPC call: | ||||
if (request.params.size() > 1 && !request.params[1].isNull()) { | if (request.params.size() > 1 && !request.params[1].isNull()) { | ||||
UniValue prevTxs = request.params[1].get_array(); | UniValue prevTxs = request.params[1].get_array(); | ||||
for (size_t idx = 0; idx < prevTxs.size(); idx++) { | for (size_t idx = 0; idx < prevTxs.size(); idx++) { | ||||
const UniValue &p = prevTxs[idx]; | const UniValue &p = prevTxs[idx]; | ||||
if (!p.isObject()) { | if (!p.isObject()) { | ||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, | throw JSONRPCError( | ||||
RPC_DESERIALIZATION_ERROR, | |||||
"expected object with " | "expected object with " | ||||
"{\"txid'\",\"vout\",\"scriptPubKey\"}"); | "{\"unspentid'\",\"vout\",\"scriptPubKey\"}"); | ||||
} | } | ||||
UniValue prevOut = p.get_obj(); | UniValue prevOut = p.get_obj(); | ||||
RPCTypeCheckObj(prevOut, | RPCTypeCheckObj(prevOut, | ||||
{ | { | ||||
{"txid", UniValueType(UniValue::VSTR)}, | {"unspentid", UniValueType(UniValue::VSTR)}, | ||||
{"vout", UniValueType(UniValue::VNUM)}, | {"vout", UniValueType(UniValue::VNUM)}, | ||||
{"scriptPubKey", UniValueType(UniValue::VSTR)}, | {"scriptPubKey", UniValueType(UniValue::VSTR)}, | ||||
// "amount" is also required but check is done | // "amount" is also required but check is done | ||||
// below due to UniValue::VNUM erroneously | // below due to UniValue::VNUM erroneously | ||||
// not accepting quoted numerics | // not accepting quoted numerics | ||||
// (which are valid JSON) | // (which are valid JSON) | ||||
}); | }); | ||||
uint256 txid = ParseHashO(prevOut, "txid"); | const unspentid_t unspentid = | ||||
unspentid_t(ParseHashO(prevOut, "unspentid")); | |||||
int nOut = find_value(prevOut, "vout").get_int(); | int nOut = find_value(prevOut, "vout").get_int(); | ||||
if (nOut < 0) { | if (nOut < 0) { | ||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, | ||||
"vout must be positive"); | "vout must be positive"); | ||||
} | } | ||||
COutPoint out(txid, nOut); | COutPoint out(unspentid, nOut); | ||||
std::vector<uint8_t> pkData(ParseHexO(prevOut, "scriptPubKey")); | std::vector<uint8_t> pkData(ParseHexO(prevOut, "scriptPubKey")); | ||||
CScript scriptPubKey(pkData.begin(), pkData.end()); | CScript scriptPubKey(pkData.begin(), pkData.end()); | ||||
{ | { | ||||
const Coin &coin = view.AccessCoin(out); | const Coin &coin = view.AccessCoin(out); | ||||
if (!coin.IsSpent() && | if (!coin.IsSpent() && | ||||
coin.GetTxOut().scriptPubKey != scriptPubKey) { | coin.GetTxOut().scriptPubKey != scriptPubKey) { | ||||
std::string err("Previous output scriptPubKey mismatch:\n"); | std::string err("Previous output scriptPubKey mismatch:\n"); | ||||
Show All 25 Lines | if (request.params.size() > 1 && !request.params[1].isNull()) { | ||||
} | } | ||||
// If redeemScript given and not using the local wallet (private | // If redeemScript given and not using the local wallet (private | ||||
// keys given), add redeemScript to the tempKeystore so it can be | // keys given), add redeemScript to the tempKeystore so it can be | ||||
// signed: | // signed: | ||||
if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) { | if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) { | ||||
RPCTypeCheckObj( | RPCTypeCheckObj( | ||||
prevOut, { | prevOut, { | ||||
{"txid", UniValueType(UniValue::VSTR)}, | {"unspentid", UniValueType(UniValue::VSTR)}, | ||||
{"vout", UniValueType(UniValue::VNUM)}, | {"vout", UniValueType(UniValue::VNUM)}, | ||||
{"scriptPubKey", UniValueType(UniValue::VSTR)}, | {"scriptPubKey", UniValueType(UniValue::VSTR)}, | ||||
{"redeemScript", UniValueType(UniValue::VSTR)}, | {"redeemScript", UniValueType(UniValue::VSTR)}, | ||||
}); | }); | ||||
UniValue v = find_value(prevOut, "redeemScript"); | UniValue v = find_value(prevOut, "redeemScript"); | ||||
if (!v.isNull()) { | if (!v.isNull()) { | ||||
std::vector<uint8_t> rsData(ParseHexV(v, "redeemScript")); | std::vector<uint8_t> rsData(ParseHexV(v, "redeemScript")); | ||||
CScript redeemScript(rsData.begin(), rsData.end()); | CScript redeemScript(rsData.begin(), rsData.end()); | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
"transaction)\n" | "transaction)\n" | ||||
"2. allowhighfees (boolean, optional, default=false) Allow high " | "2. allowhighfees (boolean, optional, default=false) Allow high " | ||||
"fees\n" | "fees\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"\"hex\" (string) The transaction hash in hex\n" | "\"hex\" (string) The transaction hash in hex\n" | ||||
"\nExamples:\n" | "\nExamples:\n" | ||||
"\nCreate a transaction\n" + | "\nCreate a transaction\n" + | ||||
HelpExampleCli("createrawtransaction", | HelpExampleCli("createrawtransaction", | ||||
"\"[{\\\"txid\\\" : " | "\"[{\\\"unspentid\\\" : " | ||||
"\\\"mytxid\\\",\\\"vout\\\":0}]\" " | "\\\"myunspentid\\\",\\\"vout\\\":0}]\" " | ||||
"\"{\\\"myaddress\\\":0.01}\"") + | "\"{\\\"myaddress\\\":0.01}\"") + | ||||
"Sign the transaction, and get back the hex\n" + | "Sign the transaction, and get back the hex\n" + | ||||
HelpExampleCli("signrawtransaction", "\"myhex\"") + | HelpExampleCli("signrawtransaction", "\"myhex\"") + | ||||
"\nSend the transaction (signed hex)\n" + | "\nSend the transaction (signed hex)\n" + | ||||
HelpExampleCli("sendrawtransaction", "\"signedhex\"") + | HelpExampleCli("sendrawtransaction", "\"signedhex\"") + | ||||
"\nAs a json rpc call\n" + | "\nAs a json rpc call\n" + | ||||
HelpExampleRpc("sendrawtransaction", "\"signedhex\"")); | HelpExampleRpc("sendrawtransaction", "\"signedhex\"")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); | RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); | ||||
// parse hex string from parameter | // parse hex string from parameter | ||||
CMutableTransaction mtx; | CMutableTransaction mtx; | ||||
if (!DecodeHexTx(mtx, request.params[0].get_str())) { | if (!DecodeHexTx(mtx, request.params[0].get_str())) { | ||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); | ||||
} | } | ||||
CTransactionRef tx(MakeTransactionRef(std::move(mtx))); | CTransactionRef tx(MakeTransactionRef(std::move(mtx))); | ||||
const uint256 &txid = tx->GetId(); | const unspentid_t &unspentid = tx->Getunspentid(); | ||||
const txhash_t &txhash = tx->GetHash(); | |||||
bool fLimitFree = false; | bool fLimitFree = false; | ||||
CAmount nMaxRawTxFee = maxTxFee; | CAmount nMaxRawTxFee = maxTxFee; | ||||
if (request.params.size() > 1 && request.params[1].get_bool()) { | if (request.params.size() > 1 && request.params[1].get_bool()) { | ||||
nMaxRawTxFee = 0; | nMaxRawTxFee = 0; | ||||
} | } | ||||
CCoinsViewCache &view = *pcoinsTip; | CCoinsViewCache &view = *pcoinsTip; | ||||
bool fHaveChain = false; | bool fHaveChain = false; | ||||
for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) { | for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) { | ||||
const Coin &existingCoin = view.AccessCoin(COutPoint(txid, o)); | const Coin &existingCoin = view.AccessCoin(COutPoint(unspentid, o)); | ||||
fHaveChain = !existingCoin.IsSpent(); | fHaveChain = !existingCoin.IsSpent(); | ||||
} | } | ||||
bool fHaveMempool = mempool.exists(txid); | bool fHaveMempool = mempool.exists(txhash); | ||||
if (!fHaveMempool && !fHaveChain) { | if (!fHaveMempool && !fHaveChain) { | ||||
// Push to local node and sync with wallets. | // Push to local node and sync with wallets. | ||||
CValidationState state; | CValidationState state; | ||||
bool fMissingInputs; | bool fMissingInputs; | ||||
if (!AcceptToMemoryPool(config, mempool, state, std::move(tx), | if (!AcceptToMemoryPool(config, mempool, state, std::move(tx), | ||||
fLimitFree, &fMissingInputs, nullptr, false, | fLimitFree, &fMissingInputs, nullptr, false, | ||||
nMaxRawTxFee)) { | nMaxRawTxFee)) { | ||||
if (state.IsInvalid()) { | if (state.IsInvalid()) { | ||||
Show All 15 Lines | static UniValue sendrawtransaction(const Config &config, | ||||
} | } | ||||
if (!g_connman) { | if (!g_connman) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_CLIENT_P2P_DISABLED, | RPC_CLIENT_P2P_DISABLED, | ||||
"Error: Peer-to-peer functionality missing or disabled"); | "Error: Peer-to-peer functionality missing or disabled"); | ||||
} | } | ||||
CInv inv(MSG_TX, txid); | CInv inv(MSG_TX, txhash); | ||||
g_connman->ForEachNode([&inv](CNode *pnode) { pnode->PushInventory(inv); }); | g_connman->ForEachNode([&inv](CNode *pnode) { pnode->PushInventory(inv); }); | ||||
return txid.GetHex(); | return txhash.GetHex(); | ||||
} | } | ||||
// clang-format off | // clang-format off | ||||
static const CRPCCommand commands[] = { | static const CRPCCommand commands[] = { | ||||
// category name actor (function) okSafeMode | // category name actor (function) okSafeMode | ||||
// ------------------- ------------------------ ---------------------- ---------- | // ------------------- ------------------------ ---------------------- ---------- | ||||
{ "rawtransactions", "getrawtransaction", getrawtransaction, true, {"txid","verbose"} }, | { "rawtransactions", "getrawtransaction", getrawtransaction, true, {"txhash","verbose"} }, | ||||
{ "rawtransactions", "createrawtransaction", createrawtransaction, true, {"inputs","outputs","locktime"} }, | { "rawtransactions", "createrawtransaction", createrawtransaction, true, {"inputs","outputs","locktime"} }, | ||||
{ "rawtransactions", "decoderawtransaction", decoderawtransaction, true, {"hexstring"} }, | { "rawtransactions", "decoderawtransaction", decoderawtransaction, true, {"hexstring"} }, | ||||
{ "rawtransactions", "decodescript", decodescript, true, {"hexstring"} }, | { "rawtransactions", "decodescript", decodescript, true, {"hexstring"} }, | ||||
{ "rawtransactions", "sendrawtransaction", sendrawtransaction, false, {"hexstring","allowhighfees"} }, | { "rawtransactions", "sendrawtransaction", sendrawtransaction, false, {"hexstring","allowhighfees"} }, | ||||
{ "rawtransactions", "signrawtransaction", signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */ | { "rawtransactions", "signrawtransaction", signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */ | ||||
{ "blockchain", "gettxoutproof", gettxoutproof, true, {"txids", "blockhash"} }, | { "blockchain", "gettxoutproof", gettxoutproof, true, {"txhashes", "blockhash"} }, | ||||
{ "blockchain", "verifytxoutproof", verifytxoutproof, true, {"proof"} }, | { "blockchain", "verifytxoutproof", verifytxoutproof, true, {"proof"} }, | ||||
}; | }; | ||||
// clang-format on | // clang-format on | ||||
void RegisterRawTransactionRPCCommands(CRPCTable &t) { | void RegisterRawTransactionRPCCommands(CRPCTable &t) { | ||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) { | for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) { | ||||
t.appendCommand(commands[vcidx].name, &commands[vcidx]); | t.appendCommand(commands[vcidx].name, &commands[vcidx]); | ||||
} | } | ||||
} | } |