2012-05-31 22:01:16 +02:00
// Copyright (c) 2010 Satoshi Nakamoto
2018-01-02 18:12:05 +01:00
// Copyright (c) 2009-2017 The Bitcoin Core developers
2014-11-20 03:19:29 +01:00
// Distributed under the MIT software license, see the accompanying
2012-05-31 22:01:16 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-10 01:57:53 +01:00
# include <chain.h>
# include <coins.h>
# include <consensus/validation.h>
# include <core_io.h>
# include <init.h>
# include <keystore.h>
# include <validation.h>
# include <validationinterface.h>
2017-09-20 03:12:25 +02:00
# include <key_io.h>
2017-11-10 01:57:53 +01:00
# include <merkleblock.h>
# include <net.h>
# include <policy/policy.h>
# include <policy/rbf.h>
# include <primitives/transaction.h>
2017-06-12 21:23:02 +02:00
# include <rpc/rawtransaction.h>
2017-11-10 01:57:53 +01:00
# include <rpc/safemode.h>
# include <rpc/server.h>
# include <script/script.h>
# include <script/script_error.h>
# include <script/sign.h>
# include <script/standard.h>
# include <txmempool.h>
# include <uint256.h>
# include <utilstrencodings.h>
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2017-11-10 01:57:53 +01:00
# include <wallet/rpcwallet.h>
2013-11-29 16:04:29 +01:00
# endif
2012-05-31 22:01:16 +02:00
2017-06-21 03:21:36 +02:00
# include <future>
2013-04-13 07:13:08 +02:00
# include <stdint.h>
2015-09-04 16:11:34 +02:00
# include <univalue.h>
2015-05-18 14:02:18 +02:00
2012-05-31 22:01:16 +02:00
2015-05-18 14:02:18 +02:00
void TxToJSON ( const CTransaction & tx , const uint256 hashBlock , UniValue & entry )
2012-05-31 22:01:16 +02:00
{
2016-09-22 02:51:00 +02:00
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
//
// Blockchain contextual information (confirmations and blocktime) is not
// available to code in bitcoin-common, so we query them here and push the
// data into the returned UniValue.
2017-08-11 21:21:14 +02:00
TxToUniv ( tx , uint256 ( ) , entry , true , RPCSerializationFlags ( ) ) ;
2012-05-31 22:01:16 +02:00
2014-12-15 09:11:16 +01:00
if ( ! hashBlock . IsNull ( ) ) {
2017-09-22 20:04:07 +02:00
entry . pushKV ( " blockhash " , hashBlock . GetHex ( ) ) ;
2018-01-12 01:23:09 +01:00
CBlockIndex * pindex = LookupBlockIndex ( hashBlock ) ;
if ( pindex ) {
2014-06-26 03:09:36 +02:00
if ( chainActive . Contains ( pindex ) ) {
2017-09-22 20:04:07 +02:00
entry . pushKV ( " confirmations " , 1 + chainActive . Height ( ) - pindex - > nHeight ) ;
entry . pushKV ( " time " , pindex - > GetBlockTime ( ) ) ;
entry . pushKV ( " blocktime " , pindex - > GetBlockTime ( ) ) ;
2012-05-31 22:01:16 +02:00
}
else
2017-09-22 20:04:07 +02:00
entry . pushKV ( " confirmations " , 0 ) ;
2012-05-31 22:01:16 +02:00
}
}
}
2016-09-22 09:46:41 +02:00
UniValue getrawtransaction ( const JSONRPCRequest & request )
2012-05-31 22:01:16 +02:00
{
2017-04-25 10:29:24 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 3 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2017-04-25 10:29:24 +02:00
" getrawtransaction \" txid \" ( verbose \" blockhash \" ) \n "
2017-01-12 00:30:50 +01:00
" \n NOTE: By default this function only works for mempool transactions. If the -txindex option is \n "
2017-04-25 10:29:24 +02:00
" enabled, it also works for blockchain transactions. If the block which contains the transaction \n "
" is known, its hash can be provided even for nodes without -txindex. Note that if a blockhash is \n "
" provided, only that block will be searched and if the transaction is in the mempool or other \n "
" blocks, or if this node does not have the given block available, the transaction will not be found. \n "
2017-01-12 00:30:50 +01:00
" DEPRECATED: for now, it also works for transactions with unspent outputs. \n "
2013-10-29 12:29:44 +01:00
" \n Return the raw transaction data. \n "
2016-10-26 14:09:54 +02:00
" \n If verbose is 'true', returns an Object with information about 'txid'. \n "
" If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'. \n "
2013-10-29 12:29:44 +01:00
" \n Arguments: \n "
" 1. \" txid \" (string, required) The transaction id \n "
2017-04-25 10:29:24 +02:00
" 2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object \n "
" 3. \" blockhash \" (string, optional) The block in which to look for the transaction \n "
2013-10-29 12:29:44 +01:00
2016-10-26 14:09:54 +02:00
" \n Result (if verbose is not set or set to false): \n "
2013-10-29 12:29:44 +01:00
" \" data \" (string) The serialized, hex-encoded data for 'txid' \n "
2016-10-26 14:09:54 +02:00
" \n Result (if verbose is set to true): \n "
2013-10-29 12:29:44 +01:00
" { \n "
2017-04-25 10:29:24 +02:00
" \" in_active_chain \" : b, (bool) Whether specified block is in the active chain or not (only present with explicit \" blockhash \" argument) \n "
2013-10-29 12:29:44 +01:00
" \" hex \" : \" data \" , (string) The serialized, hex-encoded data for 'txid' \n "
" \" txid \" : \" id \" , (string) The transaction id (same as provided) \n "
2016-01-22 18:46:11 +01:00
" \" hash \" : \" id \" , (string) The transaction hash (differs from txid for witness transactions) \n "
" \" size \" : n, (numeric) The serialized transaction size \n "
2016-01-03 18:54:50 +01:00
" \" vsize \" : n, (numeric) The virtual transaction size (differs from size for witness transactions) \n "
2018-03-26 17:20:56 +02:00
" \" weight \" : n, (numeric) The transaction's weight (between vsize*4-3 and vsize*4) \n "
2013-10-29 12:29:44 +01:00
" \" version \" : n, (numeric) The version \n "
" \" locktime \" : ttt, (numeric) The lock time \n "
" \" vin \" : [ (array of json objects) \n "
" { \n "
" \" txid \" : \" id \" , (string) The transaction id \n "
" \" vout \" : n, (numeric) \n "
" \" scriptSig \" : { (json object) The script \n "
" \" asm \" : \" asm \" , (string) asm \n "
" \" hex \" : \" hex \" (string) hex \n "
" }, \n "
" \" sequence \" : n (numeric) The script sequence number \n "
2016-01-22 18:46:11 +01:00
" \" txinwitness \" : [ \" hex \" , ...] (array of string) hex-encoded witness data (if any) \n "
2013-10-29 12:29:44 +01:00
" } \n "
" ,... \n "
" ], \n "
" \" vout \" : [ (array of json objects) \n "
" { \n "
2015-08-01 21:15:23 +02:00
" \" value \" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + " \n "
2013-10-29 12:29:44 +01:00
" \" n \" : n, (numeric) index \n "
" \" scriptPubKey \" : { (json object) \n "
" \" asm \" : \" asm \" , (string) the asm \n "
" \" hex \" : \" hex \" , (string) the hex \n "
" \" reqSigs \" : n, (numeric) The required sigs \n "
" \" type \" : \" pubkeyhash \" , (string) The type, eg 'pubkeyhash' \n "
" \" addresses \" : [ (json array of string) \n "
2016-11-21 14:39:58 +01:00
" \" address \" (string) bitcoin address \n "
2013-10-29 12:29:44 +01:00
" ,... \n "
" ] \n "
" } \n "
" } \n "
" ,... \n "
" ], \n "
" \" blockhash \" : \" hash \" , (string) the block hash \n "
" \" confirmations \" : n, (numeric) The confirmations \n "
" \" time \" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT) \n "
" \" blocktime \" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT) \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getrawtransaction " , " \" mytxid \" " )
2016-10-26 14:09:54 +02:00
+ HelpExampleCli ( " getrawtransaction " , " \" mytxid \" true " )
+ HelpExampleRpc ( " getrawtransaction " , " \" mytxid \" , true " )
2017-04-25 10:29:24 +02:00
+ HelpExampleCli ( " getrawtransaction " , " \" mytxid \" false \" myblockhash \" " )
+ HelpExampleCli ( " getrawtransaction " , " \" mytxid \" true \" myblockhash \" " )
2013-10-29 12:29:44 +01:00
) ;
2012-05-31 22:01:16 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2017-04-25 10:29:24 +02:00
bool in_active_chain = true ;
2016-09-22 09:46:41 +02:00
uint256 hash = ParseHashV ( request . params [ 0 ] , " parameter 1 " ) ;
2017-04-25 10:29:24 +02:00
CBlockIndex * blockindex = nullptr ;
2012-05-31 22:01:16 +02:00
2018-01-27 08:10:56 +01:00
if ( hash = = Params ( ) . GenesisBlock ( ) . hashMerkleRoot ) {
// Special exception for the genesis block coinbase transaction
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved " ) ;
}
2016-10-26 14:09:54 +02:00
// Accept either a bool (true) or a num (>=1) to indicate verbose output.
2012-05-31 22:01:16 +02:00
bool fVerbose = false ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) ) {
2017-05-06 05:49:18 +02:00
fVerbose = request . params [ 1 ] . isNum ( ) ? ( request . params [ 1 ] . get_int ( ) ! = 0 ) : request . params [ 1 ] . get_bool ( ) ;
2016-10-26 14:09:54 +02:00
}
2012-05-31 22:01:16 +02:00
2017-04-25 10:29:24 +02:00
if ( ! request . params [ 2 ] . isNull ( ) ) {
uint256 blockhash = ParseHashV ( request . params [ 2 ] , " parameter 3 " ) ;
2018-01-12 01:23:09 +01:00
blockindex = LookupBlockIndex ( blockhash ) ;
if ( ! blockindex ) {
2017-12-06 16:52:29 +01:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block hash not found " ) ;
2017-04-25 10:29:24 +02:00
}
2017-12-06 16:52:29 +01:00
in_active_chain = chainActive . Contains ( blockindex ) ;
2017-04-25 10:29:24 +02:00
}
2016-11-12 01:30:38 +01:00
CTransactionRef tx ;
2017-04-25 10:29:24 +02:00
uint256 hash_block ;
if ( ! GetTransaction ( hash , tx , Params ( ) . GetConsensus ( ) , hash_block , true , blockindex ) ) {
std : : string errmsg ;
if ( blockindex ) {
if ( ! ( blockindex - > nStatus & BLOCK_HAVE_DATA ) ) {
throw JSONRPCError ( RPC_MISC_ERROR , " Block not available " ) ;
}
errmsg = " No such transaction found in the provided block " ;
} else {
errmsg = fTxIndex
? " No such mempool or blockchain transaction "
: " No such mempool transaction. Use -txindex to enable blockchain transaction queries " ;
}
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , errmsg + " . Use gettransaction for wallet transactions. " ) ;
}
2012-05-31 22:01:16 +02:00
2017-04-25 10:29:24 +02:00
if ( ! fVerbose ) {
2017-08-11 00:58:25 +02:00
return EncodeHexTx ( * tx , RPCSerializationFlags ( ) ) ;
2017-04-25 10:29:24 +02:00
}
2012-05-31 22:01:16 +02:00
2015-05-10 14:48:35 +02:00
UniValue result ( UniValue : : VOBJ ) ;
2017-09-22 20:04:07 +02:00
if ( blockindex ) result . pushKV ( " in_active_chain " , in_active_chain ) ;
2017-04-25 10:29:24 +02:00
TxToJSON ( * tx , hash_block , result ) ;
2012-05-31 22:01:16 +02:00
return result ;
}
2016-09-22 09:46:41 +02:00
UniValue gettxoutproof ( const JSONRPCRequest & request )
2014-11-02 00:01:48 +01:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | ( request . params . size ( ) ! = 1 & & request . params . size ( ) ! = 2 ) )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2014-11-02 00:01:48 +01:00
" gettxoutproof [ \" txid \" ,...] ( blockhash ) \n "
" \n Returns a hex-encoded proof that \" txid \" was included in a block. \n "
" \n NOTE: By default this function only works sometimes. This is when there is an \n "
" unspent output in the utxo for this transaction. To make it always work, \n "
" you need to maintain a transaction index, using the -txindex command line option or \n "
2016-04-16 22:35:42 +02:00
" specify the block in which the transaction is included manually (by blockhash). \n "
2014-11-02 00:01:48 +01:00
" \n Arguments: \n "
" 1. \" txids \" (string) A json array of txids to filter \n "
" [ \n "
" \" txid \" (string) A transaction hash \n "
" ,... \n "
" ] \n "
2016-12-09 18:06:42 +01:00
" 2. \" blockhash \" (string, optional) If specified, looks for txid in the block with this hash \n "
2014-11-02 00:01:48 +01:00
" \n Result: \n "
" \" data \" (string) A string that is a serialized, hex-encoded data for the proof. \n "
) ;
2017-01-04 05:22:19 +01:00
std : : set < uint256 > setTxids ;
2014-11-02 00:01:48 +01:00
uint256 oneTxid ;
2016-09-22 09:46:41 +02:00
UniValue txids = request . params [ 0 ] . get_array ( ) ;
2015-05-10 13:35:44 +02:00
for ( unsigned int idx = 0 ; idx < txids . size ( ) ; idx + + ) {
2015-05-18 14:02:18 +02:00
const UniValue & txid = txids [ idx ] ;
2014-11-02 00:01:48 +01:00
if ( txid . get_str ( ) . length ( ) ! = 64 | | ! IsHex ( txid . get_str ( ) ) )
2017-01-04 05:22:19 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , std : : string ( " Invalid txid " ) + txid . get_str ( ) ) ;
2014-11-02 00:01:48 +01:00
uint256 hash ( uint256S ( txid . get_str ( ) ) ) ;
if ( setTxids . count ( hash ) )
2017-01-04 05:22:19 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , std : : string ( " Invalid parameter, duplicated txid: " ) + txid . get_str ( ) ) ;
2014-11-02 00:01:48 +01:00
setTxids . insert ( hash ) ;
oneTxid = hash ;
}
LOCK ( cs_main ) ;
2017-08-07 07:36:37 +02:00
CBlockIndex * pblockindex = nullptr ;
2014-11-02 00:01:48 +01:00
uint256 hashBlock ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) )
2014-11-02 00:01:48 +01:00
{
2016-09-22 09:46:41 +02:00
hashBlock = uint256S ( request . params [ 1 ] . get_str ( ) ) ;
2018-01-12 01:23:09 +01:00
pblockindex = LookupBlockIndex ( hashBlock ) ;
if ( ! pblockindex ) {
2014-11-02 00:01:48 +01:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
2018-01-12 01:23:09 +01:00
}
2014-11-02 00:01:48 +01:00
} else {
2017-02-10 17:04:13 +01:00
// Loop through txids and try to find which block they're in. Exit loop once a block is found.
for ( const auto & tx : setTxids ) {
const Coin & coin = AccessByTxid ( * pcoinsTip , tx ) ;
if ( ! coin . IsSpent ( ) ) {
pblockindex = chainActive [ coin . nHeight ] ;
break ;
}
2017-04-25 20:29:39 +02:00
}
2014-11-02 00:01:48 +01:00
}
2017-08-07 07:36:37 +02:00
if ( pblockindex = = nullptr )
2014-11-02 00:01:48 +01:00
{
2016-11-12 01:30:38 +01:00
CTransactionRef tx ;
2015-04-17 14:19:21 +02:00
if ( ! GetTransaction ( oneTxid , tx , Params ( ) . GetConsensus ( ) , hashBlock , false ) | | hashBlock . IsNull ( ) )
2014-11-02 00:01:48 +01:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Transaction not yet in block " ) ;
2018-01-12 01:23:09 +01:00
pblockindex = LookupBlockIndex ( hashBlock ) ;
if ( ! pblockindex ) {
2014-11-02 00:01:48 +01:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Transaction index corrupt " ) ;
2018-01-12 01:23:09 +01:00
}
2014-11-02 00:01:48 +01:00
}
CBlock block ;
2015-04-17 14:19:21 +02:00
if ( ! ReadBlockFromDisk ( block , pblockindex , Params ( ) . GetConsensus ( ) ) )
2014-11-02 00:01:48 +01:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Can't read block from disk " ) ;
unsigned int ntxFound = 0 ;
2016-11-11 02:26:00 +01:00
for ( const auto & tx : block . vtx )
if ( setTxids . count ( tx - > GetHash ( ) ) )
2014-11-02 00:01:48 +01:00
ntxFound + + ;
if ( ntxFound ! = setTxids . size ( ) )
2017-02-10 17:04:13 +01:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Not all transactions found in specified or retrieved block " ) ;
2014-11-02 00:01:48 +01:00
2015-11-06 01:32:04 +01:00
CDataStream ssMB ( SER_NETWORK , PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS ) ;
2014-11-02 00:01:48 +01:00
CMerkleBlock mb ( block , setTxids ) ;
ssMB < < mb ;
std : : string strHex = HexStr ( ssMB . begin ( ) , ssMB . end ( ) ) ;
return strHex ;
}
2016-09-22 09:46:41 +02:00
UniValue verifytxoutproof ( const JSONRPCRequest & request )
2014-11-02 00:01:48 +01:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2014-11-02 00:01:48 +01:00
" verifytxoutproof \" proof \" \n "
" \n Verifies that a proof points to a transaction in a block, returning the transaction it commits to \n "
" and throwing an RPC error if the block is not in our best chain \n "
" \n Arguments: \n "
" 1. \" proof \" (string, required) The hex-encoded proof generated by gettxoutproof \n "
" \n Result: \n "
" [ \" txid \" ] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid \n "
) ;
2016-09-22 09:46:41 +02:00
CDataStream ssMB ( ParseHexV ( request . params [ 0 ] , " proof " ) , SER_NETWORK , PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS ) ;
2014-11-02 00:01:48 +01:00
CMerkleBlock merkleBlock ;
ssMB > > merkleBlock ;
2015-05-10 14:48:35 +02:00
UniValue res ( UniValue : : VARR ) ;
2014-11-02 00:01:48 +01:00
2017-01-04 05:22:19 +01:00
std : : vector < uint256 > vMatch ;
std : : vector < unsigned int > vIndex ;
2016-02-19 01:31:12 +01:00
if ( merkleBlock . txn . ExtractMatches ( vMatch , vIndex ) ! = merkleBlock . header . hashMerkleRoot )
2014-11-02 00:01:48 +01:00
return res ;
LOCK ( cs_main ) ;
2018-01-12 01:23:09 +01:00
const CBlockIndex * pindex = LookupBlockIndex ( merkleBlock . header . GetHash ( ) ) ;
if ( ! pindex | | ! chainActive . Contains ( pindex ) ) {
2014-11-02 00:01:48 +01:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found in chain " ) ;
2018-01-12 01:23:09 +01:00
}
2014-11-02 00:01:48 +01:00
2017-06-02 03:18:57 +02:00
for ( const uint256 & hash : vMatch )
2014-11-02 00:01:48 +01:00
res . push_back ( hash . GetHex ( ) ) ;
return res ;
}
2016-09-22 09:46:41 +02:00
UniValue createrawtransaction ( const JSONRPCRequest & request )
2012-05-31 22:01:16 +02:00
{
2017-12-11 21:24:02 +01:00
if ( request . fHelp | | request . params . size ( ) < 2 | | request . params . size ( ) > 4 ) {
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2017-12-11 21:24:02 +01:00
// clang-format off
" createrawtransaction [{ \" txid \" : \" id \" , \" vout \" :n},...] [{ \" address \" :amount},{ \" data \" : \" hex \" },...] ( locktime ) ( replaceable ) \n "
2015-06-29 20:14:02 +02:00
" \n Create a transaction spending the given inputs and creating new outputs. \n "
" Outputs can be addresses or data. \n "
2012-05-31 22:01:16 +02:00
" Returns hex-encoded raw transaction. \n "
" Note that the transaction's inputs are not signed, and \n "
2013-10-29 12:29:44 +01:00
" it is not stored in the wallet or transmitted to the network. \n "
" \n Arguments: \n "
2017-03-26 12:08:44 +02:00
" 1. \" inputs \" (array, required) A json array of json objects \n "
2013-10-29 12:29:44 +01:00
" [ \n "
" { \n "
2017-12-11 21:24:02 +01:00
" \" txid \" : \" id \" , (string, required) The transaction id \n "
2016-12-09 18:06:42 +01:00
" \" vout \" :n, (numeric, required) The output number \n "
" \" sequence \" :n (numeric, optional) The sequence number \n "
" } \n "
2013-10-29 12:29:44 +01:00
" ,... \n "
" ] \n "
2017-12-11 21:24:02 +01:00
" 2. \" outputs \" (array, required) a json array with outputs (key-value pairs) \n "
" [ \n "
2013-10-29 12:29:44 +01:00
" { \n "
2017-12-11 21:24:02 +01:00
" \" address \" : x.xxx, (obj, optional) A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + " \n "
" }, \n "
" { \n "
" \" data \" : \" hex \" (obj, optional) A key-value pair. The key must be \" data \" , the value is hex encoded data \n "
2013-10-29 12:29:44 +01:00
" } \n "
2017-12-11 21:24:02 +01:00
" ,... More key-value pairs of the above form. For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also \n "
" accepted as second parameter. \n "
" ] \n "
2016-12-09 18:06:42 +01:00
" 3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs \n "
2017-06-28 23:49:04 +02:00
" 4. replaceable (boolean, optional, default=false) Marks this transaction as BIP125 replaceable. \n "
" Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible. \n "
2013-10-29 12:29:44 +01:00
" \n Result: \n "
2016-12-09 18:06:42 +01:00
" \" transaction \" (string) hex string of the transaction \n "
2013-10-29 12:29:44 +01:00
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2018-03-11 21:51:54 +01:00
+ 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}] \" , \" [{ \\ \" data \\ \" : \\ \" 00010203 \\ \" }] \" " )
2017-12-11 21:24:02 +01:00
// clang-format on
2013-10-29 12:29:44 +01:00
) ;
2017-12-11 21:24:02 +01:00
}
2012-05-31 22:01:16 +02:00
2017-12-11 21:24:02 +01:00
RPCTypeCheck ( request . params , {
UniValue : : VARR ,
UniValueType ( ) , // ARR or OBJ, checked later
UniValue : : VNUM ,
UniValue : : VBOOL
} , true
) ;
2016-09-22 09:46:41 +02:00
if ( request . params [ 0 ] . isNull ( ) | | request . params [ 1 ] . isNull ( ) )
2015-03-22 18:51:43 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, arguments 1 and 2 must be non-null " ) ;
2012-05-31 22:01:16 +02:00
2016-09-22 09:46:41 +02:00
UniValue inputs = request . params [ 0 ] . get_array ( ) ;
2017-12-11 21:24:02 +01:00
const bool outputs_is_obj = request . params [ 1 ] . isObject ( ) ;
UniValue outputs = outputs_is_obj ?
request . params [ 1 ] . get_obj ( ) :
request . params [ 1 ] . get_array ( ) ;
2012-05-31 22:01:16 +02:00
2014-06-07 13:53:27 +02:00
CMutableTransaction rawTx ;
2012-05-31 22:01:16 +02:00
2017-08-15 01:38:18 +02:00
if ( ! request . params [ 2 ] . isNull ( ) ) {
2016-09-22 09:46:41 +02:00
int64_t nLockTime = request . params [ 2 ] . get_int64 ( ) ;
2015-03-22 18:51:43 +01:00
if ( nLockTime < 0 | | nLockTime > std : : numeric_limits < uint32_t > : : max ( ) )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, locktime out of range " ) ;
rawTx . nLockTime = nLockTime ;
}
2017-08-15 01:38:18 +02:00
bool rbfOptIn = request . params [ 3 ] . isTrue ( ) ;
2017-02-02 23:15:55 +01:00
2014-08-20 21:15:16 +02:00
for ( unsigned int idx = 0 ; idx < inputs . size ( ) ; idx + + ) {
2015-05-18 14:02:18 +02:00
const UniValue & input = inputs [ idx ] ;
const UniValue & o = input . get_obj ( ) ;
2012-05-31 22:01:16 +02:00
2012-09-08 02:54:27 +02:00
uint256 txid = ParseHashO ( o , " txid " ) ;
2012-05-31 22:01:16 +02:00
2015-05-18 14:02:18 +02:00
const UniValue & vout_v = find_value ( o , " vout " ) ;
2014-08-20 21:15:16 +02:00
if ( ! vout_v . isNum ( ) )
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, missing vout key " ) ;
2012-05-31 22:01:16 +02:00
int nOutput = vout_v . get_int ( ) ;
if ( nOutput < 0 )
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, vout must be positive " ) ;
2012-05-31 22:01:16 +02:00
2017-02-02 23:15:55 +01:00
uint32_t nSequence ;
if ( rbfOptIn ) {
2017-02-03 20:13:28 +01:00
nSequence = MAX_BIP125_RBF_SEQUENCE ;
2017-02-02 23:15:55 +01:00
} else if ( rawTx . nLockTime ) {
nSequence = std : : numeric_limits < uint32_t > : : max ( ) - 1 ;
} else {
nSequence = std : : numeric_limits < uint32_t > : : max ( ) ;
}
2015-12-22 13:52:57 +01:00
// set the sequence number if passed in the parameters object
const UniValue & sequenceObj = find_value ( o , " sequence " ) ;
2016-06-08 15:34:25 +02:00
if ( sequenceObj . isNum ( ) ) {
int64_t seqNr64 = sequenceObj . get_int64 ( ) ;
2017-02-02 23:15:55 +01:00
if ( seqNr64 < 0 | | seqNr64 > std : : numeric_limits < uint32_t > : : max ( ) ) {
2016-06-08 15:34:25 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, sequence number is out of range " ) ;
2017-02-02 23:15:55 +01:00
} else {
2016-06-08 15:34:25 +02:00
nSequence = ( uint32_t ) seqNr64 ;
2017-02-02 23:15:55 +01:00
}
2016-06-08 15:34:25 +02:00
}
2015-12-22 13:52:57 +01:00
2015-03-22 18:51:43 +01:00
CTxIn in ( COutPoint ( txid , nOutput ) , CScript ( ) , nSequence ) ;
2012-05-31 22:01:16 +02:00
rawTx . vin . push_back ( in ) ;
}
2017-08-23 03:02:33 +02:00
std : : set < CTxDestination > destinations ;
2017-12-11 21:24:02 +01:00
if ( ! outputs_is_obj ) {
// Translate array of key-value pairs into dict
UniValue outputs_dict = UniValue ( UniValue : : VOBJ ) ;
for ( size_t i = 0 ; i < outputs . size ( ) ; + + i ) {
const UniValue & output = outputs [ i ] ;
if ( ! output . isObject ( ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, key-value pair not an object as expected " ) ;
}
if ( output . size ( ) ! = 1 ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, key-value pair must contain exactly one key " ) ;
}
outputs_dict . pushKVs ( output ) ;
}
outputs = std : : move ( outputs_dict ) ;
}
for ( const std : : string & name_ : outputs . getKeys ( ) ) {
2015-06-29 20:14:02 +02:00
if ( name_ = = " data " ) {
2017-12-11 21:24:02 +01:00
std : : vector < unsigned char > data = ParseHexV ( outputs [ name_ ] . getValStr ( ) , " Data " ) ;
2015-06-29 20:14:02 +02:00
CTxOut out ( 0 , CScript ( ) < < OP_RETURN < < data ) ;
rawTx . vout . push_back ( out ) ;
} else {
2017-08-23 03:02:33 +02:00
CTxDestination destination = DecodeDestination ( name_ ) ;
if ( ! IsValidDestination ( destination ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , std : : string ( " Invalid Bitcoin address: " ) + name_ ) ;
}
2012-05-31 22:01:16 +02:00
2017-08-23 03:02:33 +02:00
if ( ! destinations . insert ( destination ) . second ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , std : : string ( " Invalid parameter, duplicated address: " ) + name_ ) ;
}
2012-05-31 22:01:16 +02:00
2017-08-23 03:02:33 +02:00
CScript scriptPubKey = GetScriptForDestination ( destination ) ;
2017-12-11 21:24:02 +01:00
CAmount nAmount = AmountFromValue ( outputs [ name_ ] ) ;
2015-06-29 20:14:02 +02:00
CTxOut out ( nAmount , scriptPubKey ) ;
rawTx . vout . push_back ( out ) ;
}
2012-05-31 22:01:16 +02:00
}
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 3 ] . isNull ( ) & & rbfOptIn ! = SignalsOptInRBF ( rawTx ) ) {
2017-06-28 23:49:04 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter combination: Sequence number(s) contradict replaceable option " ) ;
2017-02-03 20:23:22 +01:00
}
2014-06-24 05:10:24 +02:00
return EncodeHexTx ( rawTx ) ;
2012-05-31 22:01:16 +02:00
}
2016-09-22 09:46:41 +02:00
UniValue decoderawtransaction ( const JSONRPCRequest & request )
2012-05-31 22:01:16 +02:00
{
2017-08-28 08:00:21 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2017-08-28 08:00:21 +02:00
" decoderawtransaction \" hexstring \" ( iswitness ) \n "
2013-10-29 12:29:44 +01:00
" \n Return a JSON object representing the serialized, hex-encoded transaction. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" hexstring \" (string, required) The transaction hex string \n "
2017-08-28 08:00:21 +02:00
" 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 "
2013-10-29 12:29:44 +01:00
" \n Result: \n "
" { \n "
2014-04-29 20:34:41 +02:00
" \" txid \" : \" id \" , (string) The transaction id \n "
2016-01-22 18:46:11 +01:00
" \" hash \" : \" id \" , (string) The transaction hash (differs from txid for witness transactions) \n "
2015-11-21 03:35:11 +01:00
" \" size \" : n, (numeric) The transaction size \n "
2016-01-03 18:54:50 +01:00
" \" vsize \" : n, (numeric) The virtual transaction size (differs from size for witness transactions) \n "
2018-03-26 17:20:56 +02:00
" \" weight \" : n, (numeric) The transaction's weight (between vsize*4 - 3 and vsize*4) \n "
2013-10-29 12:29:44 +01:00
" \" version \" : n, (numeric) The version \n "
" \" locktime \" : ttt, (numeric) The lock time \n "
" \" vin \" : [ (array of json objects) \n "
" { \n "
" \" txid \" : \" id \" , (string) The transaction id \n "
" \" vout \" : n, (numeric) The output number \n "
" \" scriptSig \" : { (json object) The script \n "
" \" asm \" : \" asm \" , (string) asm \n "
" \" hex \" : \" hex \" (string) hex \n "
" }, \n "
2016-01-22 18:46:11 +01:00
" \" txinwitness \" : [ \" hex \" , ...] (array of string) hex-encoded witness data (if any) \n "
2013-10-29 12:29:44 +01:00
" \" sequence \" : n (numeric) The script sequence number \n "
" } \n "
" ,... \n "
" ], \n "
" \" vout \" : [ (array of json objects) \n "
" { \n "
2015-08-01 21:15:23 +02:00
" \" value \" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + " \n "
2013-10-29 12:29:44 +01:00
" \" n \" : n, (numeric) index \n "
" \" scriptPubKey \" : { (json object) \n "
" \" asm \" : \" asm \" , (string) the asm \n "
" \" hex \" : \" hex \" , (string) the hex \n "
" \" reqSigs \" : n, (numeric) The required sigs \n "
" \" type \" : \" pubkeyhash \" , (string) The type, eg 'pubkeyhash' \n "
" \" addresses \" : [ (json array of string) \n "
" \" 12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc \" (string) bitcoin address \n "
" ,... \n "
" ] \n "
" } \n "
" } \n "
" ,... \n "
" ], \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " decoderawtransaction " , " \" hexstring \" " )
+ HelpExampleRpc ( " decoderawtransaction " , " \" hexstring \" " )
) ;
2012-05-31 22:01:16 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2017-08-28 08:00:21 +02:00
RPCTypeCheck ( request . params , { UniValue : : VSTR , UniValue : : VBOOL } ) ;
2014-06-24 05:10:24 +02:00
2016-11-30 23:50:20 +01:00
CMutableTransaction mtx ;
2014-06-24 05:10:24 +02:00
2017-08-28 08:00:21 +02:00
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 ) ) {
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " TX decode failed " ) ;
2017-08-28 08:00:21 +02:00
}
2012-05-31 22:01:16 +02:00
2015-05-10 13:35:44 +02:00
UniValue result ( UniValue : : VOBJ ) ;
2017-08-11 21:21:14 +02:00
TxToUniv ( CTransaction ( std : : move ( mtx ) ) , uint256 ( ) , result , false ) ;
2012-05-31 22:01:16 +02:00
return result ;
}
2016-09-22 09:46:41 +02:00
UniValue decodescript ( const JSONRPCRequest & request )
2013-07-15 07:22:10 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-11-21 14:47:36 +01:00
" decodescript \" hexstring \" \n "
2013-10-29 12:29:44 +01:00
" \n Decode a hex-encoded script. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" hexstring \" (string) the hex encoded script \n "
2013-10-29 12:29:44 +01:00
" \n Result: \n "
" { \n "
" \" asm \" : \" asm \" , (string) Script public key \n "
" \" hex \" : \" hex \" , (string) hex encoded public key \n "
" \" type \" : \" type \" , (string) The output type \n "
" \" reqSigs \" : n, (numeric) The required signatures \n "
" \" addresses \" : [ (json array of string) \n "
" \" address \" (string) bitcoin address \n "
" ,... \n "
" ], \n "
2016-09-26 23:01:10 +02:00
" \" p2sh \" , \" address \" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH). \n "
2013-10-29 12:29:44 +01:00
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " decodescript " , " \" hexstring \" " )
+ HelpExampleRpc ( " decodescript " , " \" hexstring \" " )
) ;
2013-07-15 07:22:10 +02:00
2017-06-06 21:15:28 +02:00
RPCTypeCheck ( request . params , { UniValue : : VSTR } ) ;
2013-07-15 07:22:10 +02:00
2015-05-10 14:48:35 +02:00
UniValue r ( UniValue : : VOBJ ) ;
2013-07-15 07:22:10 +02:00
CScript script ;
2016-09-22 09:46:41 +02:00
if ( request . params [ 0 ] . get_str ( ) . size ( ) > 0 ) {
2017-01-04 05:22:19 +01:00
std : : vector < unsigned char > scriptData ( ParseHexV ( request . params [ 0 ] , " argument " ) ) ;
2013-07-15 07:22:10 +02:00
script = CScript ( scriptData . begin ( ) , scriptData . end ( ) ) ;
} else {
// Empty scripts are valid
}
2016-09-22 02:51:00 +02:00
ScriptPubKeyToUniv ( script , r , false ) ;
2013-07-15 07:22:10 +02:00
2016-09-26 23:01:10 +02:00
UniValue type ;
type = find_value ( r , " type " ) ;
if ( type . isStr ( ) & & type . get_str ( ) ! = " scripthash " ) {
// P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
// don't return the address for a P2SH of the P2SH.
2017-09-22 20:04:07 +02:00
r . pushKV ( " p2sh " , EncodeDestination ( CScriptID ( script ) ) ) ;
2016-09-26 23:01:10 +02:00
}
2013-07-15 07:22:10 +02:00
return r ;
}
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
2015-05-18 14:02:18 +02:00
static void TxInErrorToJSON ( const CTxIn & txin , UniValue & vErrorsRet , const std : : string & strMessage )
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
{
2015-05-10 14:48:35 +02:00
UniValue entry ( UniValue : : VOBJ ) ;
2017-09-22 20:04:07 +02:00
entry . pushKV ( " txid " , txin . prevout . hash . ToString ( ) ) ;
entry . pushKV ( " vout " , ( uint64_t ) txin . prevout . n ) ;
2016-07-20 20:49:32 +02:00
UniValue witness ( UniValue : : VARR ) ;
for ( unsigned int i = 0 ; i < txin . scriptWitness . stack . size ( ) ; i + + ) {
witness . push_back ( HexStr ( txin . scriptWitness . stack [ i ] . begin ( ) , txin . scriptWitness . stack [ i ] . end ( ) ) ) ;
}
2017-09-22 20:04:07 +02:00
entry . pushKV ( " witness " , witness ) ;
entry . pushKV ( " scriptSig " , HexStr ( txin . scriptSig . begin ( ) , txin . scriptSig . end ( ) ) ) ;
entry . pushKV ( " sequence " , ( uint64_t ) txin . nSequence ) ;
entry . pushKV ( " error " , strMessage ) ;
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
vErrorsRet . push_back ( entry ) ;
}
2017-06-10 07:38:06 +02:00
UniValue combinerawtransaction ( const JSONRPCRequest & request )
{
if ( request . fHelp | | request . params . size ( ) ! = 1 )
throw std : : runtime_error (
" combinerawtransaction [ \" hexstring \" ,...] \n "
" \n Combine multiple partially signed transactions into one transaction. \n "
" The combined transaction may be another partially signed transaction or a \n "
" fully signed transaction. "
" \n Arguments: \n "
" 1. \" txs \" (string) A json array of hex strings of partially signed transactions \n "
" [ \n "
" \" hexstring \" (string) A transaction hash \n "
" ,... \n "
" ] \n "
" \n Result: \n "
2017-08-18 04:35:30 +02:00
" \" hex \" (string) The hex-encoded raw transaction with signature(s) \n "
2017-06-10 07:38:06 +02:00
" \n Examples: \n "
+ HelpExampleCli ( " combinerawtransaction " , " [ \" myhex1 \" , \" myhex2 \" , \" myhex3 \" ] " )
) ;
UniValue txs = request . params [ 0 ] . get_array ( ) ;
std : : vector < CMutableTransaction > txVariants ( txs . size ( ) ) ;
for ( unsigned int idx = 0 ; idx < txs . size ( ) ; idx + + ) {
if ( ! DecodeHexTx ( txVariants [ idx ] , txs [ idx ] . get_str ( ) , true ) ) {
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , strprintf ( " TX decode failed for tx %d " , idx ) ) ;
}
}
if ( txVariants . empty ( ) ) {
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " Missing transactions " ) ;
}
// mergedTx will end up with all the signatures; it
// starts as a clone of the rawtx:
CMutableTransaction mergedTx ( txVariants [ 0 ] ) ;
// Fetch previous transactions (inputs):
CCoinsView viewDummy ;
CCoinsViewCache view ( & viewDummy ) ;
{
LOCK ( cs_main ) ;
LOCK ( mempool . cs ) ;
CCoinsViewCache & viewChain = * pcoinsTip ;
CCoinsViewMemPool viewMempool ( & viewChain , mempool ) ;
view . SetBackend ( viewMempool ) ; // temporarily switch cache backend to db+mempool view
for ( const CTxIn & txin : mergedTx . vin ) {
view . AccessCoin ( txin . prevout ) ; // Load entries from viewChain into view; can fail.
}
view . SetBackend ( viewDummy ) ; // switch back to avoid locking mempool for too long
}
// Use CTransaction for the constant parts of the
// transaction to avoid rehashing.
const CTransaction txConst ( mergedTx ) ;
// Sign what we can:
for ( unsigned int i = 0 ; i < mergedTx . vin . size ( ) ; i + + ) {
CTxIn & txin = mergedTx . vin [ i ] ;
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
if ( coin . IsSpent ( ) ) {
throw JSONRPCError ( RPC_VERIFY_ERROR , " Input not found or already spent " ) ;
}
const CScript & prevPubKey = coin . out . scriptPubKey ;
const CAmount & amount = coin . out . nValue ;
SignatureData sigdata ;
// ... and merge in other signatures:
for ( const CMutableTransaction & txv : txVariants ) {
if ( txv . vin . size ( ) > i ) {
sigdata = CombineSignatures ( prevPubKey , TransactionSignatureChecker ( & txConst , i , amount ) , sigdata , DataFromTransaction ( txv , i ) ) ;
}
}
UpdateTransaction ( mergedTx , i , sigdata ) ;
}
return EncodeHexTx ( mergedTx ) ;
}
2017-06-12 21:23:02 +02:00
UniValue SignTransaction ( CMutableTransaction & mtx , const UniValue & prevTxsUnival , CBasicKeyStore * keystore , bool is_temp_keystore , const UniValue & hashType )
2012-05-31 22:01:16 +02:00
{
// Fetch previous transactions (inputs):
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 18:54:00 +02:00
CCoinsView viewDummy ;
2014-09-24 03:19:04 +02:00
CCoinsViewCache view ( & viewDummy ) ;
2012-05-31 22:01:16 +02:00
{
2017-06-12 21:23:02 +02:00
LOCK2 ( cs_main , mempool . cs ) ;
2012-07-06 16:33:34 +02:00
CCoinsViewCache & viewChain = * pcoinsTip ;
2014-09-24 03:19:04 +02:00
CCoinsViewMemPool viewMempool ( & viewChain , mempool ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 18:54:00 +02:00
view . SetBackend ( viewMempool ) ; // temporarily switch cache backend to db+mempool view
2017-06-10 07:38:06 +02:00
for ( const CTxIn & txin : mtx . vin ) {
2017-04-25 20:29:30 +02:00
view . AccessCoin ( txin . prevout ) ; // Load entries from viewChain into view; can fail.
2012-05-31 22:01:16 +02:00
}
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 18:54:00 +02:00
2012-07-06 16:33:34 +02:00
view . SetBackend ( viewDummy ) ; // switch back to avoid locking mempool for too long
2012-05-31 22:01:16 +02:00
}
// Add previous txouts given in the RPC call:
2017-06-12 21:23:02 +02:00
if ( ! prevTxsUnival . isNull ( ) ) {
UniValue prevTxs = prevTxsUnival . get_array ( ) ;
for ( unsigned int idx = 0 ; idx < prevTxs . size ( ) ; + + idx ) {
2015-05-18 14:02:18 +02:00
const UniValue & p = prevTxs [ idx ] ;
2017-06-12 21:23:02 +02:00
if ( ! p . isObject ( ) ) {
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " expected object with { \" txid' \" , \" vout \" , \" scriptPubKey \" } " ) ;
2017-06-12 21:23:02 +02:00
}
2012-05-31 22:01:16 +02:00
2015-05-13 21:29:19 +02:00
UniValue prevOut = p . get_obj ( ) ;
2012-05-31 22:01:16 +02:00
2016-06-06 17:50:50 +02:00
RPCTypeCheckObj ( prevOut ,
{
{ " txid " , UniValueType ( UniValue : : VSTR ) } ,
{ " vout " , UniValueType ( UniValue : : VNUM ) } ,
{ " scriptPubKey " , UniValueType ( UniValue : : VSTR ) } ,
} ) ;
2012-05-31 22:01:16 +02:00
2012-09-08 02:54:27 +02:00
uint256 txid = ParseHashO ( prevOut , " txid " ) ;
2012-05-31 22:01:16 +02:00
int nOut = find_value ( prevOut , " vout " ) . get_int ( ) ;
2017-06-12 21:23:02 +02:00
if ( nOut < 0 ) {
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " vout must be positive " ) ;
2017-06-12 21:23:02 +02:00
}
2012-05-31 22:01:16 +02:00
2017-04-25 20:29:30 +02:00
COutPoint out ( txid , nOut ) ;
2017-01-04 05:22:19 +01:00
std : : vector < unsigned char > pkData ( ParseHexO ( prevOut , " scriptPubKey " ) ) ;
2012-05-31 22:01:16 +02:00
CScript scriptPubKey ( pkData . begin ( ) , pkData . end ( ) ) ;
2014-09-03 09:01:24 +02:00
{
2017-04-25 20:29:30 +02:00
const Coin & coin = view . AccessCoin ( out ) ;
2017-05-31 02:58:54 +02:00
if ( ! coin . IsSpent ( ) & & coin . out . scriptPubKey ! = scriptPubKey ) {
2017-01-04 05:22:19 +01:00
std : : string err ( " Previous output scriptPubKey mismatch: \n " ) ;
2017-04-25 20:29:30 +02:00
err = err + ScriptToAsmStr ( coin . out . scriptPubKey ) + " \n vs: \n " +
2015-07-31 01:56:00 +02:00
ScriptToAsmStr ( scriptPubKey ) ;
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , err ) ;
2012-05-31 22:01:16 +02:00
}
2017-04-25 20:29:30 +02:00
Coin newcoin ;
newcoin . out . scriptPubKey = scriptPubKey ;
newcoin . out . nValue = 0 ;
2016-03-31 14:54:58 +02:00
if ( prevOut . exists ( " amount " ) ) {
2017-04-25 20:29:30 +02:00
newcoin . out . nValue = AmountFromValue ( find_value ( prevOut , " amount " ) ) ;
2016-03-31 14:54:58 +02:00
}
2017-04-25 20:29:30 +02:00
newcoin . nHeight = 1 ;
view . AddCoin ( out , std : : move ( newcoin ) , true ) ;
2012-05-31 22:01:16 +02:00
}
2012-09-08 03:05:20 +02:00
// if redeemScript given and not using the local wallet (private keys
2017-06-12 21:23:02 +02:00
// given), add redeemScript to the keystore so it can be signed:
if ( is_temp_keystore & & ( scriptPubKey . IsPayToScriptHash ( ) | | scriptPubKey . IsPayToWitnessScriptHash ( ) ) ) {
2016-06-06 17:50:50 +02:00
RPCTypeCheckObj ( prevOut ,
{
{ " redeemScript " , UniValueType ( UniValue : : VSTR ) } ,
} ) ;
2015-05-13 21:29:19 +02:00
UniValue v = find_value ( prevOut , " redeemScript " ) ;
2014-08-20 21:15:16 +02:00
if ( ! v . isNull ( ) ) {
2017-01-04 05:22:19 +01:00
std : : vector < unsigned char > rsData ( ParseHexV ( v , " redeemScript " ) ) ;
2013-02-02 04:59:42 +01:00
CScript redeemScript ( rsData . begin ( ) , rsData . end ( ) ) ;
2017-06-12 21:23:02 +02:00
keystore - > AddCScript ( redeemScript ) ;
2018-02-13 22:04:48 +01:00
// Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
2017-06-12 21:23:02 +02:00
keystore - > AddCScript ( GetScriptForWitness ( redeemScript ) ) ;
2013-02-02 04:59:42 +01:00
}
2012-09-08 03:05:20 +02:00
}
2012-05-31 22:01:16 +02:00
}
}
2012-08-20 22:18:17 +02:00
2012-07-17 18:06:13 +02:00
int nHashType = SIGHASH_ALL ;
2017-06-12 21:23:02 +02:00
if ( ! hashType . isNull ( ) ) {
2017-06-06 21:15:28 +02:00
static std : : map < std : : string , int > mapSigHashValues = {
{ std : : string ( " ALL " ) , int ( SIGHASH_ALL ) } ,
{ std : : string ( " ALL|ANYONECANPAY " ) , int ( SIGHASH_ALL | SIGHASH_ANYONECANPAY ) } ,
{ std : : string ( " NONE " ) , int ( SIGHASH_NONE ) } ,
{ std : : string ( " NONE|ANYONECANPAY " ) , int ( SIGHASH_NONE | SIGHASH_ANYONECANPAY ) } ,
{ std : : string ( " SINGLE " ) , int ( SIGHASH_SINGLE ) } ,
{ std : : string ( " SINGLE|ANYONECANPAY " ) , int ( SIGHASH_SINGLE | SIGHASH_ANYONECANPAY ) } ,
} ;
2017-06-12 21:23:02 +02:00
std : : string strHashType = hashType . get_str ( ) ;
if ( mapSigHashValues . count ( strHashType ) ) {
2012-07-17 18:06:13 +02:00
nHashType = mapSigHashValues [ strHashType ] ;
2017-06-12 21:23:02 +02:00
} else {
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid sighash param " ) ;
2017-06-12 21:23:02 +02:00
}
2012-07-17 18:06:13 +02:00
}
2012-08-20 20:06:27 +02:00
bool fHashSingle = ( ( nHashType & ~ SIGHASH_ANYONECANPAY ) = = SIGHASH_SINGLE ) ;
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
// Script verification errors
2015-05-10 14:48:35 +02:00
UniValue vErrors ( UniValue : : VARR ) ;
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
2016-05-30 11:43:53 +02:00
// Use CTransaction for the constant parts of the
// transaction to avoid rehashing.
2017-06-10 07:38:06 +02:00
const CTransaction txConst ( mtx ) ;
2012-05-31 22:01:16 +02:00
// Sign what we can:
2017-06-10 07:38:06 +02:00
for ( unsigned int i = 0 ; i < mtx . vin . size ( ) ; i + + ) {
CTxIn & txin = mtx . vin [ i ] ;
2017-04-25 20:29:30 +02:00
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
2017-05-31 02:58:54 +02:00
if ( coin . IsSpent ( ) ) {
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
TxInErrorToJSON ( txin , vErrors , " Input not found or already spent " ) ;
2012-05-31 22:01:16 +02:00
continue ;
}
2017-04-25 20:29:30 +02:00
const CScript & prevPubKey = coin . out . scriptPubKey ;
const CAmount & amount = coin . out . nValue ;
2012-05-31 22:01:16 +02:00
2016-03-31 14:54:58 +02:00
SignatureData sigdata ;
2012-08-20 20:06:27 +02:00
// Only sign SIGHASH_SINGLE if there's a corresponding output:
2017-06-12 21:23:02 +02:00
if ( ! fHashSingle | | ( i < mtx . vout . size ( ) ) ) {
2018-03-27 22:15:10 +02:00
ProduceSignature ( * keystore , MutableTransactionSignatureCreator ( & mtx , i , amount , nHashType ) , prevPubKey , sigdata ) ;
2017-06-12 21:23:02 +02:00
}
2017-06-10 07:38:06 +02:00
sigdata = CombineSignatures ( prevPubKey , TransactionSignatureChecker ( & txConst , i , amount ) , sigdata , DataFromTransaction ( mtx , i ) ) ;
2012-05-31 22:01:16 +02:00
2017-06-10 07:38:06 +02:00
UpdateTransaction ( mtx , i , sigdata ) ;
2016-03-31 14:54:58 +02:00
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
ScriptError serror = SCRIPT_ERR_OK ;
2016-08-04 02:49:16 +02:00
if ( ! VerifyScript ( txin . scriptSig , prevPubKey , & txin . scriptWitness , STANDARD_SCRIPT_VERIFY_FLAGS , TransactionSignatureChecker ( & txConst , i , amount ) , & serror ) ) {
2017-09-08 14:20:00 +02:00
if ( serror = = SCRIPT_ERR_INVALID_STACK_OPERATION ) {
// Unable to sign input and verification failed (possible attempt to partially sign).
TxInErrorToJSON ( txin , vErrors , " Unable to sign input, invalid stack size (possibly missing key) " ) ;
} else {
TxInErrorToJSON ( txin , vErrors , ScriptErrorString ( serror ) ) ;
}
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
}
2012-05-31 22:01:16 +02:00
}
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
bool fComplete = vErrors . empty ( ) ;
2012-05-31 22:01:16 +02:00
2015-05-10 14:48:35 +02:00
UniValue result ( UniValue : : VOBJ ) ;
2017-09-22 20:04:07 +02:00
result . pushKV ( " hex " , EncodeHexTx ( mtx ) ) ;
result . pushKV ( " complete " , fComplete ) ;
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
if ( ! vErrors . empty ( ) ) {
2017-09-22 20:04:07 +02:00
result . pushKV ( " errors " , vErrors ) ;
RPC: show script verification errors in "signrawtransaction" result
If there are any script verification errors, when using "signrawtransaction", they are shown in the RPC result:
```
// ...
Result:
{
"hex" : "value", (string) The hex-encoded raw transaction with signature(s)
"complete" : true|false, (boolean) If the transaction has a complete set of signatures
"errors" : [ (json array of objects) Script verification errors (if there are any)
{
"txid" : "hash", (string) The hash of the referenced, previous transaction
"vout" : n, (numeric) The index of the output to spent and used as input
"scriptSig" : "hex", (string) The hex-encoded signature script
"sequence" : n, (numeric) Script sequence number
"error" : "text" (string) Verification or signing error related to the input
}
,...
]
}
```
2015-03-22 19:07:28 +01:00
}
2012-05-31 22:01:16 +02:00
return result ;
}
2017-06-12 21:23:02 +02:00
UniValue signrawtransactionwithkey ( const JSONRPCRequest & request )
{
if ( request . fHelp | | request . params . size ( ) < 2 | | request . params . size ( ) > 4 )
throw std : : runtime_error (
" signrawtransactionwithkey \" hexstring \" [ \" privatekey1 \" ,...] ( [{ \" txid \" : \" id \" , \" vout \" :n, \" scriptPubKey \" : \" hex \" , \" redeemScript \" : \" hex \" },...] sighashtype ) \n "
" \n Sign inputs for raw transaction (serialized, hex-encoded). \n "
" The second argument is an array of base58-encoded private \n "
" keys that will be the only keys used to sign the transaction. \n "
" The third optional argument (may be null) is an array of previous transaction outputs that \n "
" this transaction depends on but may not yet be in the block chain. \n "
" \n Arguments: \n "
" 1. \" hexstring \" (string, required) The transaction hex string \n "
" 2. \" privkeys \" (string, required) A json array of base58-encoded private keys for signing \n "
" [ (json array of strings) \n "
" \" privatekey \" (string) private key in base58-encoding \n "
" ,... \n "
" ] \n "
" 3. \" prevtxs \" (string, optional) An json array of previous dependent transaction outputs \n "
" [ (json array of json objects, or 'null' if none provided) \n "
" { \n "
" \" txid \" : \" id \" , (string, required) The transaction id \n "
" \" vout \" :n, (numeric, required) The output number \n "
" \" scriptPubKey \" : \" hex \" , (string, required) script key \n "
" \" redeemScript \" : \" hex \" , (string, required for P2SH or P2WSH) redeem script \n "
" \" amount \" : value (numeric, required) The amount spent \n "
" } \n "
" ,... \n "
" ] \n "
" 4. \" sighashtype \" (string, optional, default=ALL) The signature hash type. Must be one of \n "
" \" ALL \" \n "
" \" NONE \" \n "
" \" SINGLE \" \n "
" \" ALL|ANYONECANPAY \" \n "
" \" NONE|ANYONECANPAY \" \n "
" \" SINGLE|ANYONECANPAY \" \n "
" \n Result: \n "
" { \n "
" \" hex \" : \" value \" , (string) The hex-encoded raw transaction with signature(s) \n "
" \" complete \" : true|false, (boolean) If the transaction has a complete set of signatures \n "
" \" errors \" : [ (json array of objects) Script verification errors (if there are any) \n "
" { \n "
" \" txid \" : \" hash \" , (string) The hash of the referenced, previous transaction \n "
" \" vout \" : n, (numeric) The index of the output to spent and used as input \n "
" \" scriptSig \" : \" hex \" , (string) The hex-encoded signature script \n "
" \" sequence \" : n, (numeric) Script sequence number \n "
" \" error \" : \" text \" (string) Verification or signing error related to the input \n "
" } \n "
" ,... \n "
" ] \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " signrawtransactionwithkey " , " \" myhex \" " )
+ HelpExampleRpc ( " signrawtransactionwithkey " , " \" myhex \" " )
) ;
RPCTypeCheck ( request . params , { UniValue : : VSTR , UniValue : : VARR , UniValue : : VARR , UniValue : : VSTR } , true ) ;
CMutableTransaction mtx ;
if ( ! DecodeHexTx ( mtx , request . params [ 0 ] . get_str ( ) , true ) ) {
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " TX decode failed " ) ;
}
CBasicKeyStore keystore ;
const UniValue & keys = request . params [ 1 ] . get_array ( ) ;
for ( unsigned int idx = 0 ; idx < keys . size ( ) ; + + idx ) {
UniValue k = keys [ idx ] ;
2017-09-20 01:49:52 +02:00
CKey key = DecodeSecret ( k . get_str ( ) ) ;
2017-06-12 21:23:02 +02:00
if ( ! key . IsValid ( ) ) {
2017-09-20 01:49:52 +02:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Invalid private key " ) ;
2017-06-12 21:23:02 +02:00
}
keystore . AddKey ( key ) ;
}
return SignTransaction ( mtx , request . params [ 2 ] , & keystore , true , request . params [ 3 ] ) ;
}
UniValue signrawtransaction ( const JSONRPCRequest & request )
{
# ifdef ENABLE_WALLET
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
# endif
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 4 )
throw std : : runtime_error (
" signrawtransaction \" hexstring \" ( [{ \" txid \" : \" id \" , \" vout \" :n, \" scriptPubKey \" : \" hex \" , \" redeemScript \" : \" hex \" },...] [ \" privatekey1 \" ,...] sighashtype ) \n "
" \n DEPRECATED. Sign inputs for raw transaction (serialized, hex-encoded). \n "
" The second optional argument (may be null) is an array of previous transaction outputs that \n "
" this transaction depends on but may not yet be in the block chain. \n "
" The third optional argument (may be null) is an array of base58-encoded private \n "
" keys that, if given, will be the only keys used to sign the transaction. \n "
# ifdef ENABLE_WALLET
+ HelpRequiringPassphrase ( pwallet ) + " \n "
# endif
" \n Arguments: \n "
" 1. \" hexstring \" (string, required) The transaction hex string \n "
" 2. \" prevtxs \" (string, optional) An json array of previous dependent transaction outputs \n "
" [ (json array of json objects, or 'null' if none provided) \n "
" { \n "
" \" txid \" : \" id \" , (string, required) The transaction id \n "
" \" vout \" :n, (numeric, required) The output number \n "
" \" scriptPubKey \" : \" hex \" , (string, required) script key \n "
" \" redeemScript \" : \" hex \" , (string, required for P2SH or P2WSH) redeem script \n "
" \" amount \" : value (numeric, required) The amount spent \n "
" } \n "
" ,... \n "
" ] \n "
" 3. \" privkeys \" (string, optional) A json array of base58-encoded private keys for signing \n "
" [ (json array of strings, or 'null' if none provided) \n "
" \" privatekey \" (string) private key in base58-encoding \n "
" ,... \n "
" ] \n "
" 4. \" sighashtype \" (string, optional, default=ALL) The signature hash type. Must be one of \n "
" \" ALL \" \n "
" \" NONE \" \n "
" \" SINGLE \" \n "
" \" ALL|ANYONECANPAY \" \n "
" \" NONE|ANYONECANPAY \" \n "
" \" SINGLE|ANYONECANPAY \" \n "
" \n Result: \n "
" { \n "
" \" hex \" : \" value \" , (string) The hex-encoded raw transaction with signature(s) \n "
" \" complete \" : true|false, (boolean) If the transaction has a complete set of signatures \n "
" \" errors \" : [ (json array of objects) Script verification errors (if there are any) \n "
" { \n "
" \" txid \" : \" hash \" , (string) The hash of the referenced, previous transaction \n "
" \" vout \" : n, (numeric) The index of the output to spent and used as input \n "
" \" scriptSig \" : \" hex \" , (string) The hex-encoded signature script \n "
" \" sequence \" : n, (numeric) Script sequence number \n "
" \" error \" : \" text \" (string) Verification or signing error related to the input \n "
" } \n "
" ,... \n "
" ] \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " signrawtransaction " , " \" myhex \" " )
+ HelpExampleRpc ( " signrawtransaction " , " \" myhex \" " )
) ;
if ( ! IsDeprecatedRPCEnabled ( " signrawtransaction " ) ) {
throw JSONRPCError ( RPC_METHOD_DEPRECATED , " signrawtransaction is deprecated and will be fully removed in v0.18. "
" To use signrawtransaction in v0.17, restart bitcoind with -deprecatedrpc=signrawtransaction. \n "
" Projects should transition to using signrawtransactionwithkey and signrawtransactionwithwallet before upgrading to v0.18 " ) ;
}
RPCTypeCheck ( request . params , { UniValue : : VSTR , UniValue : : VARR , UniValue : : VARR , UniValue : : VSTR } , true ) ;
// Make a JSONRPCRequest to pass on to the right signrawtransaction* command
JSONRPCRequest new_request ;
new_request . id = request . id ;
new_request . params . setArray ( ) ;
// For signing with private keys
if ( ! request . params [ 2 ] . isNull ( ) ) {
new_request . params . push_back ( request . params [ 0 ] ) ;
// Note: the prevtxs and privkeys are reversed for signrawtransactionwithkey
new_request . params . push_back ( request . params [ 2 ] ) ;
new_request . params . push_back ( request . params [ 1 ] ) ;
new_request . params . push_back ( request . params [ 3 ] ) ;
return signrawtransactionwithkey ( new_request ) ;
2018-03-26 15:19:44 +02:00
} else {
2017-06-12 21:23:02 +02:00
# ifdef ENABLE_WALLET
2018-03-26 15:19:44 +02:00
// Otherwise sign with the wallet which does not take a privkeys parameter
2017-06-12 21:23:02 +02:00
new_request . params . push_back ( request . params [ 0 ] ) ;
new_request . params . push_back ( request . params [ 1 ] ) ;
new_request . params . push_back ( request . params [ 3 ] ) ;
return signrawtransactionwithwallet ( new_request ) ;
2018-03-26 15:19:44 +02:00
# else
// If we have made it this far, then wallet is disabled and no private keys were given, so fail here.
throw JSONRPCError ( RPC_INVALID_PARAMETER , " No private keys available. " ) ;
2017-06-12 21:23:02 +02:00
# endif
2018-03-26 15:19:44 +02:00
}
2017-06-12 21:23:02 +02:00
}
2016-09-22 09:46:41 +02:00
UniValue sendrawtransaction ( const JSONRPCRequest & request )
2012-05-31 22:01:16 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2013-10-29 12:29:44 +01:00
" sendrawtransaction \" hexstring \" ( allowhighfees ) \n "
" \n Submits raw transaction (serialized, hex-encoded) to local node and network. \n "
" \n Also see createrawtransaction and signrawtransaction calls. \n "
" \n Arguments: \n "
" 1. \" hexstring \" (string, required) The hex string of the raw transaction) \n "
" 2. allowhighfees (boolean, optional, default=false) Allow high fees \n "
" \n Result: \n "
" \" hex \" (string) The transaction hash in hex \n "
" \n Examples: \n "
" \n Create a transaction \n "
+ HelpExampleCli ( " createrawtransaction " , " \" [{ \\ \" txid \\ \" : \\ \" mytxid \\ \" , \\ \" vout \\ \" :0}] \" \" { \\ \" myaddress \\ \" :0.01} \" " ) +
" Sign the transaction, and get back the hex \n "
+ HelpExampleCli ( " signrawtransaction " , " \" myhex \" " ) +
" \n Send the transaction (signed hex) \n "
+ HelpExampleCli ( " sendrawtransaction " , " \" signedhex \" " ) +
" \n As a json rpc call \n "
+ HelpExampleRpc ( " sendrawtransaction " , " \" signedhex \" " )
) ;
2017-06-09 02:38:23 +02:00
ObserveSafeMode ( ) ;
2017-06-21 03:21:36 +02:00
std : : promise < void > promise ;
2017-06-06 21:15:28 +02:00
RPCTypeCheck ( request . params , { UniValue : : VSTR , UniValue : : VBOOL } ) ;
2012-05-31 22:01:16 +02:00
// parse hex string from parameter
2016-11-30 23:50:20 +01:00
CMutableTransaction mtx ;
if ( ! DecodeHexTx ( mtx , request . params [ 0 ] . get_str ( ) ) )
2014-06-24 05:10:24 +02:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " TX decode failed " ) ;
2016-11-11 07:29:19 +01:00
CTransactionRef tx ( MakeTransactionRef ( std : : move ( mtx ) ) ) ;
const uint256 & hashTx = tx - > GetHash ( ) ;
2012-05-31 22:01:16 +02:00
2015-11-20 16:48:06 +01:00
CAmount nMaxRawTxFee = maxTxFee ;
2017-08-15 01:44:02 +02:00
if ( ! request . params [ 1 ] . isNull ( ) & & request . params [ 1 ] . get_bool ( ) )
2015-11-20 16:48:06 +01:00
nMaxRawTxFee = 0 ;
2013-08-29 00:41:46 +02:00
2017-06-21 03:21:36 +02:00
{ // cs_main scope
LOCK ( cs_main ) ;
2012-07-06 16:33:34 +02:00
CCoinsViewCache & view = * pcoinsTip ;
2017-04-25 20:29:30 +02:00
bool fHaveChain = false ;
for ( size_t o = 0 ; ! fHaveChain & & o < tx - > vout . size ( ) ; o + + ) {
const Coin & existingCoin = view . AccessCoin ( COutPoint ( hashTx , o ) ) ;
2017-05-31 02:58:54 +02:00
fHaveChain = ! existingCoin . IsSpent ( ) ;
2017-04-25 20:29:30 +02:00
}
2014-02-22 12:02:42 +01:00
bool fHaveMempool = mempool . exists ( hashTx ) ;
if ( ! fHaveMempool & & ! fHaveChain ) {
// push to local node and sync with wallets
CValidationState state ;
2014-12-03 14:13:09 +01:00
bool fMissingInputs ;
2017-09-12 18:30:26 +02:00
if ( ! AcceptToMemoryPool ( mempool , state , std : : move ( tx ) , & fMissingInputs ,
nullptr /* plTxnReplaced */ , false /* bypass_limits */ , nMaxRawTxFee ) ) {
2014-12-03 14:13:09 +01:00
if ( state . IsInvalid ( ) ) {
2018-02-07 00:47:51 +01:00
throw JSONRPCError ( RPC_TRANSACTION_REJECTED , FormatStateMessage ( state ) ) ;
2014-12-03 14:13:09 +01:00
} else {
if ( fMissingInputs ) {
throw JSONRPCError ( RPC_TRANSACTION_ERROR , " Missing inputs " ) ;
}
2018-02-07 00:47:51 +01:00
throw JSONRPCError ( RPC_TRANSACTION_ERROR , FormatStateMessage ( state ) ) ;
2014-12-03 14:13:09 +01:00
}
2017-06-21 03:21:36 +02:00
} else {
// If wallet is enabled, ensure that the wallet has been made aware
// of the new transaction prior to returning. This prevents a race
// where a user might call sendrawtransaction with a transaction
// to/from their wallet, immediately call some wallet RPC, and get
// a stale result because callbacks have not yet been processed.
CallFunctionInValidationInterfaceQueue ( [ & promise ] {
promise . set_value ( ) ;
} ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 18:54:00 +02:00
}
2014-02-22 12:02:42 +01:00
} else if ( fHaveChain ) {
throw JSONRPCError ( RPC_TRANSACTION_ALREADY_IN_CHAIN , " transaction already in block chain " ) ;
2017-11-20 21:18:52 +01:00
} else {
// Make sure we don't block forever if re-sending
// a transaction already in mempool.
promise . set_value ( ) ;
2012-07-13 01:46:24 +02:00
}
2017-06-21 03:21:36 +02:00
} // cs_main
promise . get_future ( ) . wait ( ) ;
2016-04-17 01:13:12 +02:00
if ( ! g_connman )
throw JSONRPCError ( RPC_CLIENT_P2P_DISABLED , " Error: Peer-to-peer functionality missing or disabled " ) ;
2012-05-31 22:01:16 +02:00
2016-04-17 01:13:12 +02:00
CInv inv ( MSG_TX , hashTx ) ;
g_connman - > ForEachNode ( [ & inv ] ( CNode * pnode )
{
pnode - > PushInventory ( inv ) ;
} ) ;
2017-06-21 03:21:36 +02:00
2012-07-13 01:46:24 +02:00
return hashTx . GetHex ( ) ;
2012-05-31 22:01:16 +02:00
}
2016-03-29 19:43:02 +02:00
2017-11-17 18:54:39 +01:00
UniValue testmempoolaccept ( const JSONRPCRequest & request )
{
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 ) {
throw std : : runtime_error (
// clang-format off
" testmempoolaccept [ \" rawtxs \" ] ( allowhighfees ) \n "
" \n Returns if raw transaction (serialized, hex-encoded) would be accepted by mempool. \n "
" \n This checks if the transaction violates the consensus or policy rules. \n "
" \n See sendrawtransaction call. \n "
" \n Arguments: \n "
" 1. [ \" rawtxs \" ] (array, required) An array of hex strings of raw transactions. \n "
" Length must be one for now. \n "
" 2. allowhighfees (boolean, optional, default=false) Allow high fees \n "
" \n Result: \n "
" [ (array) The result of the mempool acceptance test for each raw transaction in the input array. \n "
" Length is exactly one for now. \n "
" { \n "
" \" txid \" (string) The transaction hash in hex \n "
" \" allowed \" (boolean) If the mempool allows this tx to be inserted \n "
" \" reject-reason \" (string) Rejection string (only present when 'allowed' is false) \n "
" } \n "
" ] \n "
" \n Examples: \n "
" \n Create a transaction \n "
+ HelpExampleCli ( " createrawtransaction " , " \" [{ \\ \" txid \\ \" : \\ \" mytxid \\ \" , \\ \" vout \\ \" :0}] \" \" { \\ \" myaddress \\ \" :0.01} \" " ) +
" Sign the transaction, and get back the hex \n "
+ HelpExampleCli ( " signrawtransaction " , " \" myhex \" " ) +
" \n Test acceptance of the transaction (signed hex) \n "
+ HelpExampleCli ( " testmempoolaccept " , " \" signedhex \" " ) +
" \n As a json rpc call \n "
+ HelpExampleRpc ( " testmempoolaccept " , " [ \" signedhex \" ] " )
// clang-format on
) ;
}
ObserveSafeMode ( ) ;
RPCTypeCheck ( request . params , { UniValue : : VARR , UniValue : : VBOOL } ) ;
if ( request . params [ 0 ] . get_array ( ) . size ( ) ! = 1 ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Array must contain exactly one raw transaction for now " ) ;
}
CMutableTransaction mtx ;
if ( ! DecodeHexTx ( mtx , request . params [ 0 ] . get_array ( ) [ 0 ] . get_str ( ) ) ) {
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " TX decode failed " ) ;
}
CTransactionRef tx ( MakeTransactionRef ( std : : move ( mtx ) ) ) ;
const uint256 & tx_hash = tx - > GetHash ( ) ;
CAmount max_raw_tx_fee = : : maxTxFee ;
if ( ! request . params [ 1 ] . isNull ( ) & & request . params [ 1 ] . get_bool ( ) ) {
max_raw_tx_fee = 0 ;
}
UniValue result ( UniValue : : VARR ) ;
UniValue result_0 ( UniValue : : VOBJ ) ;
result_0 . pushKV ( " txid " , tx_hash . GetHex ( ) ) ;
CValidationState state ;
bool missing_inputs ;
bool test_accept_res ;
{
LOCK ( cs_main ) ;
test_accept_res = AcceptToMemoryPool ( mempool , state , std : : move ( tx ) , & missing_inputs ,
2018-04-02 17:16:56 +02:00
nullptr /* plTxnReplaced */ , false /* bypass_limits */ , max_raw_tx_fee , /* test_accept */ true ) ;
2017-11-17 18:54:39 +01:00
}
result_0 . pushKV ( " allowed " , test_accept_res ) ;
if ( ! test_accept_res ) {
if ( state . IsInvalid ( ) ) {
result_0 . pushKV ( " reject-reason " , strprintf ( " %i: %s " , state . GetRejectCode ( ) , state . GetRejectReason ( ) ) ) ;
} else if ( missing_inputs ) {
result_0 . pushKV ( " reject-reason " , " missing-inputs " ) ;
} else {
result_0 . pushKV ( " reject-reason " , state . GetRejectReason ( ) ) ;
}
}
result . push_back ( std : : move ( result_0 ) ) ;
return result ;
}
2016-03-29 19:43:02 +02:00
static const CRPCCommand commands [ ] =
2017-06-12 21:23:02 +02:00
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
{ " rawtransactions " , " getrawtransaction " , & getrawtransaction , { " txid " , " verbose " , " blockhash " } } ,
{ " rawtransactions " , " createrawtransaction " , & createrawtransaction , { " inputs " , " outputs " , " locktime " , " replaceable " } } ,
{ " rawtransactions " , " decoderawtransaction " , & decoderawtransaction , { " hexstring " , " iswitness " } } ,
{ " rawtransactions " , " decodescript " , & decodescript , { " hexstring " } } ,
{ " rawtransactions " , " sendrawtransaction " , & sendrawtransaction , { " hexstring " , " allowhighfees " } } ,
{ " rawtransactions " , " combinerawtransaction " , & combinerawtransaction , { " txs " } } ,
{ " rawtransactions " , " signrawtransaction " , & signrawtransaction , { " hexstring " , " prevtxs " , " privkeys " , " sighashtype " } } , /* uses wallet if enabled */
{ " rawtransactions " , " signrawtransactionwithkey " , & signrawtransactionwithkey , { " hexstring " , " privkeys " , " prevtxs " , " sighashtype " } } ,
2017-11-17 18:54:39 +01:00
{ " rawtransactions " , " testmempoolaccept " , & testmempoolaccept , { " rawtxs " , " allowhighfees " } } ,
2017-06-12 21:23:02 +02:00
{ " blockchain " , " gettxoutproof " , & gettxoutproof , { " txids " , " blockhash " } } ,
{ " blockchain " , " verifytxoutproof " , & verifytxoutproof , { " proof " } } ,
2016-03-29 19:43:02 +02:00
} ;
2016-06-07 18:42:42 +02:00
void RegisterRawTransactionRPCCommands ( CRPCTable & t )
2016-03-29 19:43:02 +02:00
{
for ( unsigned int vcidx = 0 ; vcidx < ARRAYLEN ( commands ) ; vcidx + + )
2016-06-07 18:42:42 +02:00
t . appendCommand ( commands [ vcidx ] . name , & commands [ vcidx ] ) ;
2016-03-29 19:43:02 +02:00
}