2012-05-31 13:01:16 -07:00
// Copyright (c) 2010 Satoshi Nakamoto
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 11:07:28 -07:00
// Copyright (c) 2009-2015 The Bitcoin Core developers
2014-11-19 18:19:29 -08:00
// Distributed under the MIT software license, see the accompanying
2012-05-31 13:01:16 -07:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2018-02-01 17:49:42 -08:00
# include "consensus/upgrades.h"
2015-01-24 06:57:12 -08:00
# include "consensus/validation.h"
2014-06-23 20:10:24 -07:00
# include "core_io.h"
2012-05-31 13:01:16 -07:00
# include "init.h"
2017-09-19 18:12:25 -07:00
# include "key_io.h"
2014-01-11 09:14:29 -08:00
# include "keystore.h"
# include "main.h"
2014-11-01 16:01:48 -07:00
# include "merkleblock.h"
2012-07-12 16:46:24 -07:00
# include "net.h"
2015-01-24 06:57:12 -08:00
# include "primitives/transaction.h"
2016-01-14 16:55:17 -08:00
# include "rpc/server.h"
2014-08-22 18:35:51 -07:00
# include "script/script.h"
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 11:07:28 -07:00
# include "script/script_error.h"
2014-08-27 08:22:33 -07:00
# include "script/sign.h"
2014-09-14 03:43:56 -07:00
# include "script/standard.h"
2013-04-12 22:13:08 -07:00
# include "uint256.h"
2013-11-29 07:04:29 -08:00
# ifdef ENABLE_WALLET
2015-02-03 12:09:47 -08:00
# include "wallet/wallet.h"
2013-11-29 07:04:29 -08:00
# endif
2012-05-31 13:01:16 -07:00
2013-04-12 22:13:08 -07:00
# include <stdint.h>
# include <boost/assign/list_of.hpp>
2015-09-04 07:11:34 -07:00
# include <univalue.h>
2015-05-18 05:02:18 -07:00
2014-09-14 03:43:56 -07:00
using namespace std ;
2012-05-31 13:01:16 -07:00
2015-05-18 05:02:18 -07:00
void ScriptPubKeyToJSON ( const CScript & scriptPubKey , UniValue & out , bool fIncludeHex )
2012-05-31 13:01:16 -07:00
{
txnouttype type ;
vector < CTxDestination > addresses ;
int nRequired ;
2015-07-30 16:56:00 -07:00
out . push_back ( Pair ( " asm " , ScriptToAsmStr ( scriptPubKey ) ) ) ;
2013-07-14 22:22:10 -07:00
if ( fIncludeHex )
out . push_back ( Pair ( " hex " , HexStr ( scriptPubKey . begin ( ) , scriptPubKey . end ( ) ) ) ) ;
2012-05-31 13:01:16 -07:00
2014-06-25 18:09:36 -07:00
if ( ! ExtractDestinations ( scriptPubKey , type , addresses , nRequired ) ) {
2013-10-24 01:32:35 -07:00
out . push_back ( Pair ( " type " , GetTxnOutputType ( type ) ) ) ;
2012-05-31 13:01:16 -07:00
return ;
}
out . push_back ( Pair ( " reqSigs " , nRequired ) ) ;
out . push_back ( Pair ( " type " , GetTxnOutputType ( type ) ) ) ;
2015-05-10 05:48:35 -07:00
UniValue a ( UniValue : : VARR ) ;
2017-08-22 18:02:33 -07:00
for ( const CTxDestination & addr : addresses ) {
a . push_back ( EncodeDestination ( addr ) ) ;
}
2012-05-31 13:01:16 -07:00
out . push_back ( Pair ( " addresses " , a ) ) ;
}
2017-01-06 10:15:56 -08:00
UniValue TxJoinSplitToJSON ( const CTransaction & tx ) {
2018-04-15 07:53:40 -07:00
bool useGroth = tx . fOverwintered & & tx . nVersion > = SAPLING_TX_VERSION ;
2017-01-06 10:15:56 -08:00
UniValue vjoinsplit ( UniValue : : VARR ) ;
2016-07-10 22:08:20 -07:00
for ( unsigned int i = 0 ; i < tx . vjoinsplit . size ( ) ; i + + ) {
2016-07-14 15:10:41 -07:00
const JSDescription & jsdescription = tx . vjoinsplit [ i ] ;
2017-01-06 10:15:56 -08:00
UniValue joinsplit ( UniValue : : VOBJ ) ;
2016-01-23 17:07:18 -08:00
2017-01-31 12:32:19 -08:00
joinsplit . push_back ( Pair ( " vpub_old " , ValueFromAmount ( jsdescription . vpub_old ) ) ) ;
2016-08-28 07:43:38 -07:00
joinsplit . push_back ( Pair ( " vpub_oldZat " , jsdescription . vpub_old ) ) ;
2017-01-31 12:32:19 -08:00
joinsplit . push_back ( Pair ( " vpub_new " , ValueFromAmount ( jsdescription . vpub_new ) ) ) ;
2016-08-28 07:43:38 -07:00
joinsplit . push_back ( Pair ( " vpub_newZat " , jsdescription . vpub_new ) ) ;
2017-01-31 12:32:19 -08:00
2016-07-14 15:10:41 -07:00
joinsplit . push_back ( Pair ( " anchor " , jsdescription . anchor . GetHex ( ) ) ) ;
2016-01-23 17:07:18 -08:00
{
2017-01-06 10:15:56 -08:00
UniValue nullifiers ( UniValue : : VARR ) ;
2016-07-16 15:45:41 -07:00
BOOST_FOREACH ( const uint256 nf , jsdescription . nullifiers ) {
nullifiers . push_back ( nf . GetHex ( ) ) ;
2016-01-23 17:07:18 -08:00
}
2016-07-14 15:10:41 -07:00
joinsplit . push_back ( Pair ( " nullifiers " , nullifiers ) ) ;
2016-01-23 17:07:18 -08:00
}
{
2017-01-06 10:15:56 -08:00
UniValue commitments ( UniValue : : VARR ) ;
2016-07-14 15:10:41 -07:00
BOOST_FOREACH ( const uint256 commitment , jsdescription . commitments ) {
2016-01-23 17:07:18 -08:00
commitments . push_back ( commitment . GetHex ( ) ) ;
}
2016-07-14 15:10:41 -07:00
joinsplit . push_back ( Pair ( " commitments " , commitments ) ) ;
2016-01-23 17:07:18 -08:00
}
2017-01-31 12:32:19 -08:00
joinsplit . push_back ( Pair ( " onetimePubKey " , jsdescription . ephemeralKey . GetHex ( ) ) ) ;
joinsplit . push_back ( Pair ( " randomSeed " , jsdescription . randomSeed . GetHex ( ) ) ) ;
2016-01-23 17:07:18 -08:00
{
2017-01-06 10:15:56 -08:00
UniValue macs ( UniValue : : VARR ) ;
2016-07-14 15:10:41 -07:00
BOOST_FOREACH ( const uint256 mac , jsdescription . macs ) {
2016-01-23 17:07:18 -08:00
macs . push_back ( mac . GetHex ( ) ) ;
}
2016-07-14 15:10:41 -07:00
joinsplit . push_back ( Pair ( " macs " , macs ) ) ;
2016-01-23 17:07:18 -08:00
}
2017-01-31 12:32:19 -08:00
CDataStream ssProof ( SER_NETWORK , PROTOCOL_VERSION ) ;
2018-04-15 07:53:40 -07:00
auto ps = SproutProofSerializer < CDataStream > ( ssProof , useGroth ) ;
boost : : apply_visitor ( ps , jsdescription . proof ) ;
2017-01-31 12:32:19 -08:00
joinsplit . push_back ( Pair ( " proof " , HexStr ( ssProof . begin ( ) , ssProof . end ( ) ) ) ) ;
{
2017-01-06 10:15:56 -08:00
UniValue ciphertexts ( UniValue : : VARR ) ;
2017-01-31 12:32:19 -08:00
for ( const ZCNoteEncryption : : Ciphertext ct : jsdescription . ciphertexts ) {
ciphertexts . push_back ( HexStr ( ct . begin ( ) , ct . end ( ) ) ) ;
}
joinsplit . push_back ( Pair ( " ciphertexts " , ciphertexts ) ) ;
}
2016-01-23 17:07:18 -08:00
2016-07-14 15:10:41 -07:00
vjoinsplit . push_back ( joinsplit ) ;
2016-01-23 17:07:18 -08:00
}
2016-10-06 18:55:14 -07:00
return vjoinsplit ;
}
2018-09-17 09:44:43 -07:00
UniValue TxShieldedSpendsToJSON ( const CTransaction & tx ) {
UniValue vdesc ( UniValue : : VARR ) ;
for ( const SpendDescription & spendDesc : tx . vShieldedSpend ) {
UniValue obj ( UniValue : : VOBJ ) ;
obj . push_back ( Pair ( " cv " , spendDesc . cv . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " anchor " , spendDesc . anchor . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " nullifier " , spendDesc . nullifier . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " rk " , spendDesc . rk . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " proof " , HexStr ( spendDesc . zkproof . begin ( ) , spendDesc . zkproof . end ( ) ) ) ) ;
obj . push_back ( Pair ( " spendAuthSig " , HexStr ( spendDesc . spendAuthSig . begin ( ) , spendDesc . spendAuthSig . end ( ) ) ) ) ;
vdesc . push_back ( obj ) ;
}
return vdesc ;
}
UniValue TxShieldedOutputsToJSON ( const CTransaction & tx ) {
UniValue vdesc ( UniValue : : VARR ) ;
for ( const OutputDescription & outputDesc : tx . vShieldedOutput ) {
UniValue obj ( UniValue : : VOBJ ) ;
obj . push_back ( Pair ( " cv " , outputDesc . cv . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " cmu " , outputDesc . cm . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " ephemeralKey " , outputDesc . ephemeralKey . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " encCiphertext " , HexStr ( outputDesc . encCiphertext . begin ( ) , outputDesc . encCiphertext . end ( ) ) ) ) ;
obj . push_back ( Pair ( " outCiphertext " , HexStr ( outputDesc . outCiphertext . begin ( ) , outputDesc . outCiphertext . end ( ) ) ) ) ;
obj . push_back ( Pair ( " proof " , HexStr ( outputDesc . zkproof . begin ( ) , outputDesc . zkproof . end ( ) ) ) ) ;
vdesc . push_back ( obj ) ;
}
return vdesc ;
}
2016-07-08 19:46:52 -07:00
void TxToJSONExpanded ( const CTransaction & tx , const uint256 hashBlock , UniValue & entry ,
int nHeight = 0 , int nConfirmations = 0 , int nBlockTime = 0 )
2016-10-06 18:55:14 -07:00
{
2016-04-12 09:31:21 -07:00
uint256 txid = tx . GetHash ( ) ;
entry . push_back ( Pair ( " txid " , txid . GetHex ( ) ) ) ;
2018-02-15 22:19:36 -08:00
entry . push_back ( Pair ( " overwintered " , tx . fOverwintered ) ) ;
2016-10-06 18:55:14 -07:00
entry . push_back ( Pair ( " version " , tx . nVersion ) ) ;
2018-02-15 22:19:36 -08:00
if ( tx . fOverwintered ) {
entry . push_back ( Pair ( " versiongroupid " , HexInt ( tx . nVersionGroupId ) ) ) ;
}
2016-10-06 18:55:14 -07:00
entry . push_back ( Pair ( " locktime " , ( int64_t ) tx . nLockTime ) ) ;
2018-02-15 22:19:36 -08:00
if ( tx . fOverwintered ) {
entry . push_back ( Pair ( " expiryheight " , ( int64_t ) tx . nExpiryHeight ) ) ;
}
2015-05-10 05:48:35 -07:00
UniValue vin ( UniValue : : VARR ) ;
2016-10-06 18:55:14 -07:00
BOOST_FOREACH ( const CTxIn & txin , tx . vin ) {
2015-05-10 05:48:35 -07:00
UniValue in ( UniValue : : VOBJ ) ;
2016-10-06 18:55:14 -07:00
if ( tx . IsCoinBase ( ) )
in . push_back ( Pair ( " coinbase " , HexStr ( txin . scriptSig . begin ( ) , txin . scriptSig . end ( ) ) ) ) ;
else {
in . push_back ( Pair ( " txid " , txin . prevout . hash . GetHex ( ) ) ) ;
in . push_back ( Pair ( " vout " , ( int64_t ) txin . prevout . n ) ) ;
2015-05-10 05:48:35 -07:00
UniValue o ( UniValue : : VOBJ ) ;
2015-07-30 16:56:00 -07:00
o . push_back ( Pair ( " asm " , ScriptToAsmStr ( txin . scriptSig , true ) ) ) ;
2016-10-06 18:55:14 -07:00
o . push_back ( Pair ( " hex " , HexStr ( txin . scriptSig . begin ( ) , txin . scriptSig . end ( ) ) ) ) ;
in . push_back ( Pair ( " scriptSig " , o ) ) ;
2016-05-13 08:43:29 -07:00
// Add address and value info if spentindex enabled
CSpentIndexValue spentInfo ;
CSpentIndexKey spentKey ( txin . prevout . hash , txin . prevout . n ) ;
if ( GetSpentIndex ( spentKey , spentInfo ) ) {
in . push_back ( Pair ( " value " , ValueFromAmount ( spentInfo . satoshis ) ) ) ;
in . push_back ( Pair ( " valueSat " , spentInfo . satoshis ) ) ;
if ( spentInfo . addressType = = 1 ) {
2018-09-08 15:51:53 -07:00
in . push_back ( Pair ( " address " , EncodeDestination ( CKeyID ( spentInfo . addressHash ) ) ) ) ;
2016-05-13 08:43:29 -07:00
} else if ( spentInfo . addressType = = 2 ) {
2018-09-08 15:51:53 -07:00
in . push_back ( Pair ( " address " , EncodeDestination ( CScriptID ( spentInfo . addressHash ) ) ) ) ;
2016-05-13 08:43:29 -07:00
}
}
2016-10-06 18:55:14 -07:00
}
in . push_back ( Pair ( " sequence " , ( int64_t ) txin . nSequence ) ) ;
vin . push_back ( in ) ;
}
entry . push_back ( Pair ( " vin " , vin ) ) ;
2015-05-10 05:48:35 -07:00
UniValue vout ( UniValue : : VARR ) ;
2016-10-06 18:55:14 -07:00
for ( unsigned int i = 0 ; i < tx . vout . size ( ) ; i + + ) {
const CTxOut & txout = tx . vout [ i ] ;
2015-05-10 05:48:35 -07:00
UniValue out ( UniValue : : VOBJ ) ;
2016-10-06 18:55:14 -07:00
out . push_back ( Pair ( " value " , ValueFromAmount ( txout . nValue ) ) ) ;
2016-05-12 13:16:44 -07:00
out . push_back ( Pair ( " valueSat " , txout . nValue ) ) ;
2016-10-06 18:55:14 -07:00
out . push_back ( Pair ( " n " , ( int64_t ) i ) ) ;
2015-05-10 05:48:35 -07:00
UniValue o ( UniValue : : VOBJ ) ;
2016-10-06 18:55:14 -07:00
ScriptPubKeyToJSON ( txout . scriptPubKey , o , true ) ;
out . push_back ( Pair ( " scriptPubKey " , o ) ) ;
2016-04-12 09:31:21 -07:00
// Add spent information if spentindex is enabled
CSpentIndexValue spentInfo ;
CSpentIndexKey spentKey ( txid , i ) ;
if ( GetSpentIndex ( spentKey , spentInfo ) ) {
out . push_back ( Pair ( " spentTxId " , spentInfo . txid . GetHex ( ) ) ) ;
out . push_back ( Pair ( " spentIndex " , ( int ) spentInfo . inputIndex ) ) ;
2016-04-12 12:31:19 -07:00
out . push_back ( Pair ( " spentHeight " , spentInfo . blockHeight ) ) ;
2016-04-12 09:31:21 -07:00
}
2016-10-06 18:55:14 -07:00
vout . push_back ( out ) ;
}
entry . push_back ( Pair ( " vout " , vout ) ) ;
2016-01-23 17:07:18 -08:00
2017-01-06 10:15:56 -08:00
UniValue vjoinsplit = TxJoinSplitToJSON ( tx ) ;
2016-07-10 22:08:20 -07:00
entry . push_back ( Pair ( " vjoinsplit " , vjoinsplit ) ) ;
2016-01-23 17:07:18 -08:00
2018-09-17 09:44:43 -07:00
if ( tx . fOverwintered & & tx . nVersion > = SAPLING_TX_VERSION ) {
entry . push_back ( Pair ( " valueBalance " , ValueFromAmount ( tx . valueBalance ) ) ) ;
2018-09-17 15:34:48 -07:00
entry . push_back ( Pair ( " valueBalanceZat " , tx . valueBalance ) ) ;
2018-09-17 09:44:43 -07:00
UniValue vspenddesc = TxShieldedSpendsToJSON ( tx ) ;
entry . push_back ( Pair ( " vShieldedSpend " , vspenddesc ) ) ;
UniValue voutputdesc = TxShieldedOutputsToJSON ( tx ) ;
entry . push_back ( Pair ( " vShieldedOutput " , voutputdesc ) ) ;
if ( ! ( vspenddesc . empty ( ) & & voutputdesc . empty ( ) ) ) {
entry . push_back ( Pair ( " bindingSig " , HexStr ( tx . bindingSig . begin ( ) , tx . bindingSig . end ( ) ) ) ) ;
}
}
2016-07-08 19:46:52 -07:00
if ( ! hashBlock . IsNull ( ) ) {
entry . push_back ( Pair ( " blockhash " , hashBlock . GetHex ( ) ) ) ;
if ( nConfirmations > 0 ) {
entry . push_back ( Pair ( " height " , nHeight ) ) ;
entry . push_back ( Pair ( " confirmations " , nConfirmations ) ) ;
entry . push_back ( Pair ( " time " , nBlockTime ) ) ;
entry . push_back ( Pair ( " blocktime " , nBlockTime ) ) ;
} else {
entry . push_back ( Pair ( " height " , - 1 ) ) ;
entry . push_back ( Pair ( " confirmations " , 0 ) ) ;
}
}
}
void TxToJSON ( const CTransaction & tx , const uint256 hashBlock , UniValue & entry )
{
uint256 txid = tx . GetHash ( ) ;
entry . push_back ( Pair ( " txid " , txid . GetHex ( ) ) ) ;
entry . push_back ( Pair ( " size " , ( int ) : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) ) ) ;
entry . push_back ( Pair ( " version " , tx . nVersion ) ) ;
entry . push_back ( Pair ( " locktime " , ( int64_t ) tx . nLockTime ) ) ;
UniValue vin ( UniValue : : VARR ) ;
BOOST_FOREACH ( const CTxIn & txin , tx . vin ) {
UniValue in ( UniValue : : VOBJ ) ;
if ( tx . IsCoinBase ( ) )
in . push_back ( Pair ( " coinbase " , HexStr ( txin . scriptSig . begin ( ) , txin . scriptSig . end ( ) ) ) ) ;
else {
in . push_back ( Pair ( " txid " , txin . prevout . hash . GetHex ( ) ) ) ;
in . push_back ( Pair ( " vout " , ( int64_t ) txin . prevout . n ) ) ;
UniValue o ( UniValue : : VOBJ ) ;
2018-09-08 15:51:53 -07:00
o . push_back ( Pair ( " asm " , ScriptToAsmStr ( txin . scriptSig , true ) ) ) ;
2016-07-08 19:46:52 -07:00
o . push_back ( Pair ( " hex " , HexStr ( txin . scriptSig . begin ( ) , txin . scriptSig . end ( ) ) ) ) ;
in . push_back ( Pair ( " scriptSig " , o ) ) ;
}
in . push_back ( Pair ( " sequence " , ( int64_t ) txin . nSequence ) ) ;
vin . push_back ( in ) ;
}
entry . push_back ( Pair ( " vin " , vin ) ) ;
UniValue vout ( UniValue : : VARR ) ;
for ( unsigned int i = 0 ; i < tx . vout . size ( ) ; i + + ) {
const CTxOut & txout = tx . vout [ i ] ;
UniValue out ( UniValue : : VOBJ ) ;
out . push_back ( Pair ( " value " , ValueFromAmount ( txout . nValue ) ) ) ;
out . push_back ( Pair ( " valueSat " , txout . nValue ) ) ;
out . push_back ( Pair ( " n " , ( int64_t ) i ) ) ;
UniValue o ( UniValue : : VOBJ ) ;
ScriptPubKeyToJSON ( txout . scriptPubKey , o , true ) ;
out . push_back ( Pair ( " scriptPubKey " , o ) ) ;
vout . push_back ( out ) ;
}
entry . push_back ( Pair ( " vout " , vout ) ) ;
2014-12-15 00:11:16 -08:00
if ( ! hashBlock . IsNull ( ) ) {
2012-05-31 13:01:16 -07:00
entry . push_back ( Pair ( " blockhash " , hashBlock . GetHex ( ) ) ) ;
2014-09-03 17:02:44 -07:00
BlockMap : : iterator mi = mapBlockIndex . find ( hashBlock ) ;
2014-06-25 18:09:36 -07:00
if ( mi ! = mapBlockIndex . end ( ) & & ( * mi ) . second ) {
2012-05-31 13:01:16 -07:00
CBlockIndex * pindex = ( * mi ) . second ;
2014-06-25 18:09:36 -07:00
if ( chainActive . Contains ( pindex ) ) {
2016-03-22 10:55:19 -07:00
entry . push_back ( Pair ( " height " , pindex - > nHeight ) ) ;
2013-10-10 14:07:44 -07:00
entry . push_back ( Pair ( " confirmations " , 1 + chainActive . Height ( ) - pindex - > nHeight ) ) ;
2014-06-28 14:36:06 -07:00
entry . push_back ( Pair ( " time " , pindex - > GetBlockTime ( ) ) ) ;
entry . push_back ( Pair ( " blocktime " , pindex - > GetBlockTime ( ) ) ) ;
2016-03-22 10:55:19 -07:00
} else {
entry . push_back ( Pair ( " height " , - 1 ) ) ;
2012-05-31 13:01:16 -07:00
entry . push_back ( Pair ( " confirmations " , 0 ) ) ;
2016-03-22 10:55:19 -07:00
}
2012-05-31 13:01:16 -07:00
}
}
}
2015-05-18 05:02:18 -07:00
UniValue getrawtransaction ( const UniValue & params , bool fHelp )
2012-05-31 13:01:16 -07:00
{
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 2 )
throw runtime_error (
2013-10-29 04:29:44 -07:00
" getrawtransaction \" txid \" ( verbose ) \n "
2014-10-03 16:48:12 -07:00
" \n NOTE: By default this function only works sometimes. This is when the tx is in the mempool \n "
" or there is an 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. \n "
2013-10-29 04:29:44 -07:00
" \n Return the raw transaction data. \n "
" \n If verbose=0, returns a string that is serialized, hex-encoded data for 'txid'. \n "
" If verbose is non-zero, returns an Object with information about 'txid'. \n "
" \n Arguments: \n "
" 1. \" txid \" (string, required) The transaction id \n "
" 2. verbose (numeric, optional, default=0) If 0, return a string, other return a json object \n "
" \n Result (if verbose is not set or set to 0): \n "
" \" data \" (string) The serialized, hex-encoded data for 'txid' \n "
" \n Result (if verbose > 0): \n "
" { \n "
" \" hex \" : \" data \" , (string) The serialized, hex-encoded data for 'txid' \n "
" \" txid \" : \" id \" , (string) The transaction id (same as provided) \n "
" \" version \" : n, (numeric) The version \n "
" \" locktime \" : ttt, (numeric) The lock time \n "
2018-02-21 20:21:06 -08:00
" \" expiryheight \" : ttt, (numeric, optional) The block height after which the transaction expires \n "
2013-10-29 04:29:44 -07:00
" \" 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 "
" } \n "
" ,... \n "
" ], \n "
" \" vout \" : [ (array of json objects) \n "
" { \n "
2015-08-01 12:15:23 -07:00
" \" value \" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + " \n "
2013-10-29 04:29:44 -07: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 "
2017-03-23 15:29:56 -07:00
" \" zcashaddress \" (string) Zcash address \n "
2013-10-29 04:29:44 -07:00
" ,... \n "
" ] \n "
" } \n "
" } \n "
" ,... \n "
" ], \n "
2017-01-31 12:32:19 -08:00
" \" vjoinsplit \" : [ (array of json objects, only for version >= 2) \n "
" { \n "
2017-08-03 10:49:04 -07:00
" \" vpub_old \" : x.xxx, (numeric) public input value in " + CURRENCY_UNIT + " \n "
" \" vpub_new \" : x.xxx, (numeric) public output value in " + CURRENCY_UNIT + " \n "
2017-01-31 12:32:19 -08:00
" \" anchor \" : \" hex \" , (string) the anchor \n "
" \" nullifiers \" : [ (json array of string) \n "
" \" hex \" (string) input note nullifier \n "
" ,... \n "
" ], \n "
" \" commitments \" : [ (json array of string) \n "
" \" hex \" (string) output note commitment \n "
" ,... \n "
" ], \n "
" \" onetimePubKey \" : \" hex \" , (string) the onetime public key used to encrypt the ciphertexts \n "
" \" randomSeed \" : \" hex \" , (string) the random seed \n "
" \" macs \" : [ (json array of string) \n "
" \" hex \" (string) input note MAC \n "
" ,... \n "
" ], \n "
" \" proof \" : \" hex \" , (string) the zero-knowledge proof \n "
" \" ciphertexts \" : [ (json array of string) \n "
" \" hex \" (string) output note ciphertext \n "
" ,... \n "
" ] \n "
" } \n "
" ,... \n "
" ], \n "
2013-10-29 04:29:44 -07:00
" \" 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 \" " )
+ HelpExampleCli ( " getrawtransaction " , " \" mytxid \" 1 " )
+ HelpExampleRpc ( " getrawtransaction " , " \" mytxid \" , 1 " )
) ;
2012-05-31 13:01:16 -07:00
2012-09-07 17:54:27 -07:00
uint256 hash = ParseHashV ( params [ 0 ] , " parameter 1 " ) ;
2012-05-31 13:01:16 -07:00
bool fVerbose = false ;
if ( params . size ( ) > 1 )
fVerbose = ( params [ 1 ] . get_int ( ) ! = 0 ) ;
CTransaction tx ;
2016-07-08 19:46:52 -07:00
2014-12-15 00:11:16 -08:00
uint256 hashBlock ;
2016-07-08 19:46:52 -07:00
int nHeight = 0 ;
int nConfirmations = 0 ;
int nBlockTime = 0 ;
{
LOCK ( cs_main ) ;
if ( ! GetTransaction ( hash , tx , hashBlock , true ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " No information available about transaction " ) ;
BlockMap : : iterator mi = mapBlockIndex . find ( hashBlock ) ;
if ( mi ! = mapBlockIndex . end ( ) & & ( * mi ) . second ) {
CBlockIndex * pindex = ( * mi ) . second ;
if ( chainActive . Contains ( pindex ) ) {
nHeight = pindex - > nHeight ;
nConfirmations = 1 + chainActive . Height ( ) - pindex - > nHeight ;
nBlockTime = pindex - > GetBlockTime ( ) ;
} else {
nHeight = - 1 ;
nConfirmations = 0 ;
nBlockTime = pindex - > GetBlockTime ( ) ;
}
}
}
2012-05-31 13:01:16 -07:00
2014-06-23 20:10:24 -07:00
string strHex = EncodeHexTx ( tx ) ;
2012-05-31 13:01:16 -07:00
if ( ! fVerbose )
return strHex ;
2015-05-10 05:48:35 -07:00
UniValue result ( UniValue : : VOBJ ) ;
2012-05-31 13:01:16 -07:00
result . push_back ( Pair ( " hex " , strHex ) ) ;
2016-07-08 19:46:52 -07:00
TxToJSONExpanded ( tx , hashBlock , result , nHeight , nConfirmations , nBlockTime ) ;
2012-05-31 13:01:16 -07:00
return result ;
}
2015-05-18 05:02:18 -07:00
UniValue gettxoutproof ( const UniValue & params , bool fHelp )
2014-11-01 16:01:48 -07:00
{
if ( fHelp | | ( params . size ( ) ! = 1 & & params . size ( ) ! = 2 ) )
throw runtime_error (
" 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 "
" specify the block in which the transaction is included in manually (by blockhash). \n "
" \n Return the raw transaction data. \n "
" \n Arguments: \n "
" 1. \" txids \" (string) A json array of txids to filter \n "
" [ \n "
" \" txid \" (string) A transaction hash \n "
" ,... \n "
" ] \n "
" 2. \" block hash \" (string, optional) If specified, looks for txid in the block with this hash \n "
" \n Result: \n "
" \" data \" (string) A string that is a serialized, hex-encoded data for the proof. \n "
) ;
set < uint256 > setTxids ;
uint256 oneTxid ;
2015-05-13 12:29:19 -07:00
UniValue txids = params [ 0 ] . get_array ( ) ;
2017-02-06 16:43:10 -08:00
for ( size_t idx = 0 ; idx < txids . size ( ) ; idx + + ) {
2015-05-18 05:02:18 -07:00
const UniValue & txid = txids [ idx ] ;
2014-11-01 16:01:48 -07:00
if ( txid . get_str ( ) . length ( ) ! = 64 | | ! IsHex ( txid . get_str ( ) ) )
throw JSONRPCError ( RPC_INVALID_PARAMETER , string ( " Invalid txid " ) + txid . get_str ( ) ) ;
uint256 hash ( uint256S ( txid . get_str ( ) ) ) ;
if ( setTxids . count ( hash ) )
throw JSONRPCError ( RPC_INVALID_PARAMETER , string ( " Invalid parameter, duplicated txid: " ) + txid . get_str ( ) ) ;
setTxids . insert ( hash ) ;
oneTxid = hash ;
}
LOCK ( cs_main ) ;
CBlockIndex * pblockindex = NULL ;
uint256 hashBlock ;
if ( params . size ( ) > 1 )
{
hashBlock = uint256S ( params [ 1 ] . get_str ( ) ) ;
if ( ! mapBlockIndex . count ( hashBlock ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
pblockindex = mapBlockIndex [ hashBlock ] ;
} else {
CCoins coins ;
if ( pcoinsTip - > GetCoins ( oneTxid , coins ) & & coins . nHeight > 0 & & coins . nHeight < = chainActive . Height ( ) )
pblockindex = chainActive [ coins . nHeight ] ;
}
if ( pblockindex = = NULL )
{
CTransaction tx ;
if ( ! GetTransaction ( oneTxid , tx , hashBlock , false ) | | hashBlock . IsNull ( ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Transaction not yet in block " ) ;
if ( ! mapBlockIndex . count ( hashBlock ) )
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Transaction index corrupt " ) ;
pblockindex = mapBlockIndex [ hashBlock ] ;
}
CBlock block ;
if ( ! ReadBlockFromDisk ( block , pblockindex ) )
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Can't read block from disk " ) ;
unsigned int ntxFound = 0 ;
BOOST_FOREACH ( const CTransaction & tx , block . vtx )
2016-08-30 12:49:38 -07:00
if ( setTxids . count ( tx . GetHash ( ) ) )
2014-11-01 16:01:48 -07:00
ntxFound + + ;
if ( ntxFound ! = setTxids . size ( ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " (Not all) transactions not found in specified block " ) ;
CDataStream ssMB ( SER_NETWORK , PROTOCOL_VERSION ) ;
CMerkleBlock mb ( block , setTxids ) ;
ssMB < < mb ;
std : : string strHex = HexStr ( ssMB . begin ( ) , ssMB . end ( ) ) ;
return strHex ;
}
2015-05-18 05:02:18 -07:00
UniValue verifytxoutproof ( const UniValue & params , bool fHelp )
2014-11-01 16:01:48 -07:00
{
if ( fHelp | | params . size ( ) ! = 1 )
throw runtime_error (
" 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 "
) ;
CDataStream ssMB ( ParseHexV ( params [ 0 ] , " proof " ) , SER_NETWORK , PROTOCOL_VERSION ) ;
CMerkleBlock merkleBlock ;
ssMB > > merkleBlock ;
2015-05-10 05:48:35 -07:00
UniValue res ( UniValue : : VARR ) ;
2014-11-01 16:01:48 -07:00
vector < uint256 > vMatch ;
if ( merkleBlock . txn . ExtractMatches ( vMatch ) ! = merkleBlock . header . hashMerkleRoot )
return res ;
LOCK ( cs_main ) ;
if ( ! mapBlockIndex . count ( merkleBlock . header . GetHash ( ) ) | | ! chainActive . Contains ( mapBlockIndex [ merkleBlock . header . GetHash ( ) ] ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found in chain " ) ;
BOOST_FOREACH ( const uint256 & hash , vMatch )
res . push_back ( hash . GetHex ( ) ) ;
return res ;
}
2015-05-18 05:02:18 -07:00
UniValue createrawtransaction ( const UniValue & params , bool fHelp )
2012-05-31 13:01:16 -07:00
{
2018-06-14 03:50:52 -07:00
if ( fHelp | | params . size ( ) < 2 | | params . size ( ) > 4 )
2012-05-31 13:01:16 -07:00
throw runtime_error (
2018-07-29 20:57:33 -07:00
" createrawtransaction [{ \" txid \" : \" id \" , \" vout \" :n},...] { \" address \" :amount,...} ( locktime ) ( expiryheight ) \n "
2013-10-29 04:29:44 -07:00
" \n Create a transaction spending the given inputs and sending to the given addresses. \n "
2012-05-31 13:01:16 -07:00
" Returns hex-encoded raw transaction. \n "
" Note that the transaction's inputs are not signed, and \n "
2013-10-29 04:29:44 -07:00
" it is not stored in the wallet or transmitted to the network. \n "
" \n Arguments: \n "
" 1. \" transactions \" (string, required) A json array of json objects \n "
" [ \n "
" { \n "
2018-07-29 20:57:33 -07:00
" \" txid \" : \" id \" , (string, required) The transaction id \n "
2013-10-29 04:29:44 -07:00
" \" vout \" :n (numeric, required) The output number \n "
2015-12-22 04:52:57 -08:00
" \" sequence \" :n (numeric, optional) The sequence number \n "
2013-10-29 04:29:44 -07:00
" } \n "
" ,... \n "
" ] \n "
" 2. \" addresses \" (string, required) a json object with addresses as keys and amounts as values \n "
" { \n "
2018-03-02 03:45:05 -08:00
" \" address \" : x.xxx (numeric, required) The key is the Zcash address, the value is the " + CURRENCY_UNIT + " amount \n "
2013-10-29 04:29:44 -07:00
" ,... \n "
" } \n "
2018-07-29 20:57:33 -07:00
" 3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs \n "
" 4. expiryheight (numeric, optional, default= " + strprintf ( " %d " , DEFAULT_TX_EXPIRY_DELTA ) + " ) Expiry height of transaction (if Overwinter is active) \n "
2013-10-29 04:29:44 -07:00
" \n Result: \n "
" \" transaction \" (string) hex string of the transaction \n "
" \n Examples \n "
+ HelpExampleCli ( " createrawtransaction " , " \" [{ \\ \" txid \\ \" : \\ \" myid \\ \" , \\ \" vout \\ \" :0}] \" \" { \\ \" address \\ \" :0.01} \" " )
+ HelpExampleRpc ( " createrawtransaction " , " \" [{ \\ \" txid \\ \" : \\ \" myid \\ \" , \\ \" vout \\ \" :0}] \" , \" { \\ \" address \\ \" :0.01} \" " )
) ;
2012-05-31 13:01:16 -07:00
2014-10-19 01:46:17 -07:00
LOCK ( cs_main ) ;
2018-06-14 03:50:52 -07:00
RPCTypeCheck ( params , boost : : assign : : list_of ( UniValue : : VARR ) ( UniValue : : VOBJ ) ( UniValue : : VNUM ) ( UniValue : : VNUM ) , true ) ;
2015-03-22 10:51:43 -07:00
if ( params [ 0 ] . isNull ( ) | | params [ 1 ] . isNull ( ) )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, arguments 1 and 2 must be non-null " ) ;
2012-05-31 13:01:16 -07:00
2015-05-13 12:29:19 -07:00
UniValue inputs = params [ 0 ] . get_array ( ) ;
UniValue sendTo = params [ 1 ] . get_obj ( ) ;
2012-05-31 13:01:16 -07:00
2018-02-21 20:21:06 -08:00
int nextBlockHeight = chainActive . Height ( ) + 1 ;
2018-02-15 22:19:36 -08:00
CMutableTransaction rawTx = CreateNewContextualCMutableTransaction (
2018-02-21 20:21:06 -08:00
Params ( ) . GetConsensus ( ) , nextBlockHeight ) ;
2012-05-31 13:01:16 -07:00
2015-03-22 10:51:43 -07:00
if ( params . size ( ) > 2 & & ! params [ 2 ] . isNull ( ) ) {
int64_t nLockTime = params [ 2 ] . get_int64 ( ) ;
if ( nLockTime < 0 | | nLockTime > std : : numeric_limits < uint32_t > : : max ( ) )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, locktime out of range " ) ;
rawTx . nLockTime = nLockTime ;
}
2018-06-14 03:50:52 -07:00
2018-07-29 20:57:33 -07:00
if ( params . size ( ) > 3 & & ! params [ 3 ] . isNull ( ) ) {
if ( NetworkUpgradeActive ( nextBlockHeight , Params ( ) . GetConsensus ( ) , Consensus : : UPGRADE_OVERWINTER ) ) {
2018-06-14 03:50:52 -07:00
int64_t nExpiryHeight = params [ 3 ] . get_int64 ( ) ;
if ( nExpiryHeight < 0 | | nExpiryHeight > = TX_EXPIRY_HEIGHT_THRESHOLD ) {
2018-07-29 20:57:33 -07:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " Invalid parameter, expiryheight must be nonnegative and less than %d. " , TX_EXPIRY_HEIGHT_THRESHOLD ) ) ;
2018-06-14 03:50:52 -07:00
}
rawTx . nExpiryHeight = nExpiryHeight ;
2018-07-29 20:57:33 -07:00
} else {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, expiryheight can only be used if Overwinter is active when the transaction is mined " ) ;
2018-06-14 03:50:52 -07:00
}
}
2015-03-22 10:51:43 -07:00
2017-02-06 16:43:10 -08:00
for ( size_t idx = 0 ; idx < inputs . size ( ) ; idx + + ) {
2015-05-18 05:02:18 -07:00
const UniValue & input = inputs [ idx ] ;
const UniValue & o = input . get_obj ( ) ;
2012-05-31 13:01:16 -07:00
2012-09-07 17:54:27 -07:00
uint256 txid = ParseHashO ( o , " txid " ) ;
2012-05-31 13:01:16 -07:00
2015-05-18 05:02:18 -07:00
const UniValue & vout_v = find_value ( o , " vout " ) ;
2014-08-20 12:15:16 -07:00
if ( ! vout_v . isNum ( ) )
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, missing vout key " ) ;
2012-05-31 13:01:16 -07:00
int nOutput = vout_v . get_int ( ) ;
if ( nOutput < 0 )
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, vout must be positive " ) ;
2012-05-31 13:01:16 -07:00
2015-03-22 10:51:43 -07:00
uint32_t nSequence = ( rawTx . nLockTime ? std : : numeric_limits < uint32_t > : : max ( ) - 1 : std : : numeric_limits < uint32_t > : : max ( ) ) ;
2015-12-22 04:52:57 -08:00
// set the sequence number if passed in the parameters object
const UniValue & sequenceObj = find_value ( o , " sequence " ) ;
if ( sequenceObj . isNum ( ) )
nSequence = sequenceObj . get_int ( ) ;
2015-03-22 10:51:43 -07:00
CTxIn in ( COutPoint ( txid , nOutput ) , CScript ( ) , nSequence ) ;
2012-05-31 13:01:16 -07:00
rawTx . vin . push_back ( in ) ;
}
2017-08-22 18:02:33 -07:00
std : : set < CTxDestination > destinations ;
2014-08-20 12:15:16 -07:00
vector < string > addrList = sendTo . getKeys ( ) ;
2017-08-22 18:02:33 -07:00
for ( const std : : string & name_ : addrList ) {
CTxDestination destination = DecodeDestination ( name_ ) ;
if ( ! IsValidDestination ( destination ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , std : : string ( " Invalid Zcash address: " ) + name_ ) ;
}
2012-05-31 13:01:16 -07:00
2017-08-22 18:02:33 -07:00
if ( ! destinations . insert ( destination ) . second ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , std : : string ( " Invalid parameter, duplicated address: " ) + name_ ) ;
}
2012-05-31 13:01:16 -07:00
2017-08-22 18:02:33 -07:00
CScript scriptPubKey = GetScriptForDestination ( destination ) ;
2014-08-20 12:15:16 -07:00
CAmount nAmount = AmountFromValue ( sendTo [ name_ ] ) ;
2012-05-31 13:01:16 -07:00
CTxOut out ( nAmount , scriptPubKey ) ;
rawTx . vout . push_back ( out ) ;
}
2014-06-23 20:10:24 -07:00
return EncodeHexTx ( rawTx ) ;
2012-05-31 13:01:16 -07:00
}
2015-05-18 05:02:18 -07:00
UniValue decoderawtransaction ( const UniValue & params , bool fHelp )
2012-05-31 13:01:16 -07:00
{
if ( fHelp | | params . size ( ) ! = 1 )
throw runtime_error (
2013-10-29 04:29:44 -07:00
" decoderawtransaction \" hexstring \" \n "
" \n Return a JSON object representing the serialized, hex-encoded transaction. \n "
" \n Arguments: \n "
2014-04-29 11:34:41 -07:00
" 1. \" hex \" (string, required) The transaction hex string \n "
2013-10-29 04:29:44 -07:00
" \n Result: \n "
" { \n "
2014-04-29 11:34:41 -07:00
" \" txid \" : \" id \" , (string) The transaction id \n "
2018-02-21 20:21:06 -08:00
" \" overwintered \" : bool (boolean) The Overwintered flag \n "
2013-10-29 04:29:44 -07:00
" \" version \" : n, (numeric) The version \n "
2018-02-15 22:19:36 -08:00
" \" versiongroupid \" : \" hex \" (string, optional) The version group id (Overwintered txs) \n "
2013-10-29 04:29:44 -07:00
" \" locktime \" : ttt, (numeric) The lock time \n "
2018-02-15 22:19:36 -08:00
" \" expiryheight \" : n, (numeric, optional) Last valid block height for mining transaction (Overwintered txs) \n "
2013-10-29 04:29:44 -07:00
" \" 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 "
" \" sequence \" : n (numeric) The script sequence number \n "
" } \n "
" ,... \n "
" ], \n "
" \" vout \" : [ (array of json objects) \n "
" { \n "
2015-08-01 12:15:23 -07:00
" \" value \" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + " \n "
2013-10-29 04:29:44 -07: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 "
2017-10-03 17:48:00 -07:00
" \" t12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc \" (string) zcash address \n "
2013-10-29 04:29:44 -07:00
" ,... \n "
" ] \n "
" } \n "
" } \n "
" ,... \n "
" ], \n "
2017-01-31 12:32:19 -08:00
" \" vjoinsplit \" : [ (array of json objects, only for version >= 2) \n "
" { \n "
2017-08-03 10:49:04 -07:00
" \" vpub_old \" : x.xxx, (numeric) public input value in " + CURRENCY_UNIT + " \n "
" \" vpub_new \" : x.xxx, (numeric) public output value in " + CURRENCY_UNIT + " \n "
2017-01-31 12:32:19 -08:00
" \" anchor \" : \" hex \" , (string) the anchor \n "
" \" nullifiers \" : [ (json array of string) \n "
" \" hex \" (string) input note nullifier \n "
" ,... \n "
" ], \n "
" \" commitments \" : [ (json array of string) \n "
" \" hex \" (string) output note commitment \n "
" ,... \n "
" ], \n "
" \" onetimePubKey \" : \" hex \" , (string) the onetime public key used to encrypt the ciphertexts \n "
" \" randomSeed \" : \" hex \" , (string) the random seed \n "
" \" macs \" : [ (json array of string) \n "
" \" hex \" (string) input note MAC \n "
" ,... \n "
" ], \n "
" \" proof \" : \" hex \" , (string) the zero-knowledge proof \n "
" \" ciphertexts \" : [ (json array of string) \n "
" \" hex \" (string) output note ciphertext \n "
" ,... \n "
" ] \n "
" } \n "
" ,... \n "
" ], \n "
2013-10-29 04:29:44 -07:00
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " decoderawtransaction " , " \" hexstring \" " )
+ HelpExampleRpc ( " decoderawtransaction " , " \" hexstring \" " )
) ;
2012-05-31 13:01:16 -07:00
2014-10-19 01:46:17 -07:00
LOCK ( cs_main ) ;
2014-08-20 12:15:16 -07:00
RPCTypeCheck ( params , boost : : assign : : list_of ( UniValue : : VSTR ) ) ;
2014-06-23 20:10:24 -07:00
2012-05-31 13:01:16 -07:00
CTransaction tx ;
2014-06-23 20:10:24 -07:00
if ( ! DecodeHexTx ( tx , params [ 0 ] . get_str ( ) ) )
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " TX decode failed " ) ;
2012-05-31 13:01:16 -07:00
2015-05-10 04:35:44 -07:00
UniValue result ( UniValue : : VOBJ ) ;
2014-12-15 00:11:16 -08:00
TxToJSON ( tx , uint256 ( ) , result ) ;
2012-05-31 13:01:16 -07:00
return result ;
}
2015-05-18 05:02:18 -07:00
UniValue decodescript ( const UniValue & params , bool fHelp )
2013-07-14 22:22:10 -07:00
{
if ( fHelp | | params . size ( ) ! = 1 )
throw runtime_error (
2013-10-29 04:29:44 -07:00
" decodescript \" hex \" \n "
" \n Decode a hex-encoded script. \n "
" \n Arguments: \n "
" 1. \" hex \" (string) the hex encoded script \n "
" \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 "
2017-03-23 15:29:56 -07:00
" \" address \" (string) Zcash address \n "
2013-10-29 04:29:44 -07:00
" ,... \n "
" ], \n "
" \" p2sh \" , \" address \" (string) script address \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " decodescript " , " \" hexstring \" " )
+ HelpExampleRpc ( " decodescript " , " \" hexstring \" " )
) ;
2013-07-14 22:22:10 -07:00
2014-10-19 01:46:17 -07:00
LOCK ( cs_main ) ;
2015-05-10 04:35:44 -07:00
RPCTypeCheck ( params , boost : : assign : : list_of ( UniValue : : VSTR ) ) ;
2013-07-14 22:22:10 -07:00
2015-05-10 05:48:35 -07:00
UniValue r ( UniValue : : VOBJ ) ;
2013-07-14 22:22:10 -07:00
CScript script ;
if ( params [ 0 ] . get_str ( ) . size ( ) > 0 ) {
vector < unsigned char > scriptData ( ParseHexV ( params [ 0 ] , " argument " ) ) ;
script = CScript ( scriptData . begin ( ) , scriptData . end ( ) ) ;
} else {
// Empty scripts are valid
}
ScriptPubKeyToJSON ( script , r , false ) ;
2017-08-22 18:02:33 -07:00
r . push_back ( Pair ( " p2sh " , EncodeDestination ( CScriptID ( script ) ) ) ) ;
2013-07-14 22:22:10 -07: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 11:07:28 -07:00
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
2015-05-18 05:02:18 -07: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 11:07:28 -07:00
{
2015-05-10 05:48:35 -07:00
UniValue entry ( UniValue : : VOBJ ) ;
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 11:07:28 -07:00
entry . push_back ( Pair ( " txid " , txin . prevout . hash . ToString ( ) ) ) ;
entry . push_back ( Pair ( " vout " , ( uint64_t ) txin . prevout . n ) ) ;
entry . push_back ( Pair ( " scriptSig " , HexStr ( txin . scriptSig . begin ( ) , txin . scriptSig . end ( ) ) ) ) ;
entry . push_back ( Pair ( " sequence " , ( uint64_t ) txin . nSequence ) ) ;
entry . push_back ( Pair ( " error " , strMessage ) ) ;
vErrorsRet . push_back ( entry ) ;
}
2015-05-18 05:02:18 -07:00
UniValue signrawtransaction ( const UniValue & params , bool fHelp )
2012-05-31 13:01:16 -07:00
{
2012-07-17 09:06:13 -07:00
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 4 )
2012-05-31 13:01:16 -07:00
throw runtime_error (
2013-10-29 04:29:44 -07:00
" signrawtransaction \" hexstring \" ( [{ \" txid \" : \" id \" , \" vout \" :n, \" scriptPubKey \" : \" hex \" , \" redeemScript \" : \" hex \" },...] [ \" privatekey1 \" ,...] sighashtype ) \n "
" \n 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 "
2012-10-05 10:22:21 -07:00
" this transaction depends on but may not yet be in the block chain. \n "
2013-10-29 04:29:44 -07:00
" The third optional argument (may be null) is an array of base58-encoded private \n "
2012-05-31 13:01:16 -07:00
" keys that, if given, will be the only keys used to sign the transaction. \n "
2013-11-29 07:04:29 -08:00
# ifdef ENABLE_WALLET
2013-10-29 04:29:44 -07:00
+ HelpRequiringPassphrase ( ) + " \n "
2013-11-29 07:04:29 -08:00
# endif
2013-10-29 04:29:44 -07:00
" \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 "
2014-02-22 12:51:23 -08:00
" [ (json array of json objects, or 'null' if none provided) \n "
2013-10-29 04:29:44 -07:00
" { \n "
" \" txid \" : \" id \" , (string, required) The transaction id \n "
" \" vout \" :n, (numeric, required) The output number \n "
" \" scriptPubKey \" : \" hex \" , (string, required) script key \n "
2016-03-31 05:54:58 -07:00
" \" redeemScript \" : \" hex \" , (string, required for P2SH) redeem script \n "
" \" amount \" : value (numeric, required) The amount spent \n "
2013-10-29 04:29:44 -07:00
" } \n "
" ,... \n "
" ] \n "
" 3. \" privatekeys \" (string, optional) A json array of base58-encoded private keys for signing \n "
2014-02-22 12:51:23 -08:00
" [ (json array of strings, or 'null' if none provided) \n "
2013-10-29 04:29:44 -07:00
" \" privatekey \" (string) private key in base58-encoding \n "
" ,... \n "
" ] \n "
2014-04-08 08:53:41 -07:00
" 4. \" sighashtype \" (string, optional, default=ALL) The signature hash type. Must be one of \n "
2013-10-29 04:29:44 -07:00
" \" ALL \" \n "
" \" NONE \" \n "
" \" SINGLE \" \n "
" \" ALL|ANYONECANPAY \" \n "
" \" NONE|ANYONECANPAY \" \n "
" \" SINGLE|ANYONECANPAY \" \n "
" \n Result: \n "
" { \n "
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 11:07:28 -07:00
" \" 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 "
2013-10-29 04:29:44 -07:00
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " signrawtransaction " , " \" myhex \" " )
+ HelpExampleRpc ( " signrawtransaction " , " \" myhex \" " )
) ;
2012-05-31 13:01:16 -07:00
2014-10-19 01:46:17 -07:00
# ifdef ENABLE_WALLET
LOCK2 ( cs_main , pwalletMain ? & pwalletMain - > cs_wallet : NULL ) ;
# else
LOCK ( cs_main ) ;
# endif
2014-08-20 12:15:16 -07:00
RPCTypeCheck ( params , boost : : assign : : list_of ( UniValue : : VSTR ) ( UniValue : : VARR ) ( UniValue : : VARR ) ( UniValue : : VSTR ) , true ) ;
2012-05-31 13:01:16 -07:00
2012-09-07 17:54:27 -07:00
vector < unsigned char > txData ( ParseHexV ( params [ 0 ] , " argument 1 " ) ) ;
2012-05-31 13:01:16 -07:00
CDataStream ssData ( txData , SER_NETWORK , PROTOCOL_VERSION ) ;
2014-06-07 04:53:27 -07:00
vector < CMutableTransaction > txVariants ;
2014-06-25 18:09:36 -07:00
while ( ! ssData . empty ( ) ) {
2012-05-31 13:01:16 -07:00
try {
2014-06-07 04:53:27 -07:00
CMutableTransaction tx ;
2012-05-31 13:01:16 -07:00
ssData > > tx ;
txVariants . push_back ( tx ) ;
}
2014-12-07 04:29:06 -08:00
catch ( const std : : exception & ) {
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " TX decode failed " ) ;
2012-05-31 13:01:16 -07:00
}
}
if ( txVariants . empty ( ) )
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " Missing transaction " ) ;
2012-05-31 13:01:16 -07:00
// mergedTx will end up with all the signatures; it
// starts as a clone of the rawtx:
2014-06-07 04:53:27 -07:00
CMutableTransaction mergedTx ( txVariants [ 0 ] ) ;
2012-05-31 13:01:16 -07: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 09:54:00 -07:00
CCoinsView viewDummy ;
2014-09-23 18:19:04 -07:00
CCoinsViewCache view ( & viewDummy ) ;
2012-05-31 13:01:16 -07: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 09:54:00 -07:00
LOCK ( mempool . cs ) ;
2012-07-06 07:33:34 -07:00
CCoinsViewCache & viewChain = * pcoinsTip ;
2014-09-23 18:19:04 -07: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 09:54:00 -07:00
view . SetBackend ( viewMempool ) ; // temporarily switch cache backend to db+mempool view
BOOST_FOREACH ( const CTxIn & txin , mergedTx . vin ) {
2012-05-31 13:01:16 -07:00
const uint256 & prevHash = txin . prevout . hash ;
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 09:54:00 -07:00
CCoins coins ;
2014-09-02 12:21:15 -07:00
view . AccessCoins ( prevHash ) ; // this is certainly allowed to fail
2012-05-31 13:01:16 -07: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 09:54:00 -07:00
2012-07-06 07:33:34 -07:00
view . SetBackend ( viewDummy ) ; // switch back to avoid locking mempool for too long
2012-05-31 13:01:16 -07:00
}
2012-09-07 18:05:20 -07:00
bool fGivenKeys = false ;
CBasicKeyStore tempKeystore ;
2014-08-20 12:15:16 -07:00
if ( params . size ( ) > 2 & & ! params [ 2 ] . isNull ( ) ) {
2012-09-07 18:05:20 -07:00
fGivenKeys = true ;
2015-05-13 12:29:19 -07:00
UniValue keys = params [ 2 ] . get_array ( ) ;
2017-02-06 16:43:10 -08:00
for ( size_t idx = 0 ; idx < keys . size ( ) ; idx + + ) {
2015-05-13 12:29:19 -07:00
UniValue k = keys [ idx ] ;
2017-09-19 16:49:52 -07:00
CKey key = DecodeSecret ( k . get_str ( ) ) ;
2014-12-11 07:06:23 -08:00
if ( ! key . IsValid ( ) )
2017-09-19 16:49:52 -07:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Invalid private key " ) ;
2012-09-07 18:05:20 -07:00
tempKeystore . AddKey ( key ) ;
}
}
2013-11-29 07:04:29 -08:00
# ifdef ENABLE_WALLET
2014-10-19 01:46:17 -07:00
else if ( pwalletMain )
2012-09-07 18:05:20 -07:00
EnsureWalletIsUnlocked ( ) ;
2013-11-29 07:04:29 -08:00
# endif
2012-09-07 18:05:20 -07:00
2012-05-31 13:01:16 -07:00
// Add previous txouts given in the RPC call:
2014-08-20 12:15:16 -07:00
if ( params . size ( ) > 1 & & ! params [ 1 ] . isNull ( ) ) {
2015-05-13 12:29:19 -07:00
UniValue prevTxs = params [ 1 ] . get_array ( ) ;
2017-02-06 16:43:10 -08:00
for ( size_t idx = 0 ; idx < prevTxs . size ( ) ; idx + + ) {
2015-05-18 05:02:18 -07:00
const UniValue & p = prevTxs [ idx ] ;
2014-08-20 12:15:16 -07:00
if ( ! p . isObject ( ) )
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " expected object with { \" txid' \" , \" vout \" , \" scriptPubKey \" } " ) ;
2012-05-31 13:01:16 -07:00
2015-05-13 12:29:19 -07:00
UniValue prevOut = p . get_obj ( ) ;
2012-05-31 13:01:16 -07:00
2014-08-20 12:15:16 -07:00
RPCTypeCheckObj ( prevOut , boost : : assign : : map_list_of ( " txid " , UniValue : : VSTR ) ( " vout " , UniValue : : VNUM ) ( " scriptPubKey " , UniValue : : VSTR ) ) ;
2012-05-31 13:01:16 -07:00
2012-09-07 17:54:27 -07:00
uint256 txid = ParseHashO ( prevOut , " txid " ) ;
2012-05-31 13:01:16 -07:00
int nOut = find_value ( prevOut , " vout " ) . get_int ( ) ;
if ( nOut < 0 )
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " vout must be positive " ) ;
2012-05-31 13:01:16 -07:00
2012-09-07 17:54:27 -07:00
vector < unsigned char > pkData ( ParseHexO ( prevOut , " scriptPubKey " ) ) ;
2012-05-31 13:01:16 -07:00
CScript scriptPubKey ( pkData . begin ( ) , pkData . end ( ) ) ;
2014-09-03 00:01:24 -07:00
{
CCoinsModifier coins = view . ModifyCoins ( txid ) ;
if ( coins - > IsAvailable ( nOut ) & & coins - > vout [ nOut ] . scriptPubKey ! = scriptPubKey ) {
2012-05-31 13:01:16 -07:00
string err ( " Previous output scriptPubKey mismatch: \n " ) ;
2015-07-30 16:56:00 -07:00
err = err + ScriptToAsmStr ( coins - > vout [ nOut ] . scriptPubKey ) + " \n vs: \n " +
ScriptToAsmStr ( scriptPubKey ) ;
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , err ) ;
2012-05-31 13:01:16 -07:00
}
2014-09-03 00:01:24 -07:00
if ( ( unsigned int ) nOut > = coins - > vout . size ( ) )
coins - > vout . resize ( nOut + 1 ) ;
coins - > vout [ nOut ] . scriptPubKey = scriptPubKey ;
2016-03-31 05:54:58 -07:00
coins - > vout [ nOut ] . nValue = 0 ;
if ( prevOut . exists ( " amount " ) ) {
coins - > vout [ nOut ] . nValue = AmountFromValue ( find_value ( prevOut , " amount " ) ) ;
}
2012-05-31 13:01:16 -07:00
}
2012-09-07 18:05:20 -07:00
// if redeemScript given and not using the local wallet (private keys
// given), add redeemScript to the tempKeystore so it can be signed:
2014-06-25 18:09:36 -07:00
if ( fGivenKeys & & scriptPubKey . IsPayToScriptHash ( ) ) {
2014-08-20 12:15:16 -07:00
RPCTypeCheckObj ( prevOut , boost : : assign : : map_list_of ( " txid " , UniValue : : VSTR ) ( " vout " , UniValue : : VNUM ) ( " scriptPubKey " , UniValue : : VSTR ) ( " redeemScript " , UniValue : : VSTR ) ) ;
2015-05-13 12:29:19 -07:00
UniValue v = find_value ( prevOut , " redeemScript " ) ;
2014-08-20 12:15:16 -07:00
if ( ! v . isNull ( ) ) {
2013-02-01 19:59:42 -08:00
vector < unsigned char > rsData ( ParseHexV ( v , " redeemScript " ) ) ;
CScript redeemScript ( rsData . begin ( ) , rsData . end ( ) ) ;
tempKeystore . AddCScript ( redeemScript ) ;
}
2012-09-07 18:05:20 -07:00
}
2012-05-31 13:01:16 -07:00
}
}
2012-08-20 13:18:17 -07:00
2013-11-29 07:04:29 -08:00
# ifdef ENABLE_WALLET
2013-08-24 21:00:02 -07:00
const CKeyStore & keystore = ( ( fGivenKeys | | ! pwalletMain ) ? tempKeystore : * pwalletMain ) ;
2013-11-29 07:04:29 -08:00
# else
const CKeyStore & keystore = tempKeystore ;
# endif
2012-05-31 13:01:16 -07:00
2012-07-17 09:06:13 -07:00
int nHashType = SIGHASH_ALL ;
2014-08-20 12:15:16 -07:00
if ( params . size ( ) > 3 & & ! params [ 3 ] . isNull ( ) ) {
2012-07-17 09:06:13 -07:00
static map < string , int > mapSigHashValues =
boost : : assign : : map_list_of
( string ( " ALL " ) , int ( SIGHASH_ALL ) )
( string ( " ALL|ANYONECANPAY " ) , int ( SIGHASH_ALL | SIGHASH_ANYONECANPAY ) )
( string ( " NONE " ) , int ( SIGHASH_NONE ) )
( string ( " NONE|ANYONECANPAY " ) , int ( SIGHASH_NONE | SIGHASH_ANYONECANPAY ) )
( string ( " SINGLE " ) , int ( SIGHASH_SINGLE ) )
( string ( " SINGLE|ANYONECANPAY " ) , int ( SIGHASH_SINGLE | SIGHASH_ANYONECANPAY ) )
;
string strHashType = params [ 3 ] . get_str ( ) ;
if ( mapSigHashValues . count ( strHashType ) )
nHashType = mapSigHashValues [ strHashType ] ;
else
2012-10-04 00:34:44 -07:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid sighash param " ) ;
2012-07-17 09:06:13 -07:00
}
2012-08-20 11:06:27 -07:00
bool fHashSingle = ( ( nHashType & ~ SIGHASH_ANYONECANPAY ) = = SIGHASH_SINGLE ) ;
2018-02-01 17:49:42 -08:00
// Grab the current consensus branch ID
auto consensusBranchId = CurrentEpochBranchId ( chainActive . Height ( ) + 1 , Params ( ) . GetConsensus ( ) ) ;
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 11:07:28 -07:00
// Script verification errors
2015-05-10 05:48:35 -07: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 11:07:28 -07:00
2016-05-30 02:43:53 -07:00
// Use CTransaction for the constant parts of the
// transaction to avoid rehashing.
const CTransaction txConst ( mergedTx ) ;
2012-05-31 13:01:16 -07:00
// Sign what we can:
2014-06-25 18:09:36 -07:00
for ( unsigned int i = 0 ; i < mergedTx . vin . size ( ) ; i + + ) {
2012-05-31 13:01:16 -07:00
CTxIn & txin = mergedTx . vin [ i ] ;
2014-09-02 12:21:15 -07:00
const CCoins * coins = view . AccessCoins ( txin . prevout . hash ) ;
if ( coins = = NULL | | ! coins - > IsAvailable ( txin . prevout . n ) ) {
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 11:07:28 -07:00
TxInErrorToJSON ( txin , vErrors , " Input not found or already spent " ) ;
2012-05-31 13:01:16 -07:00
continue ;
}
2014-09-02 12:21:15 -07:00
const CScript & prevPubKey = coins - > vout [ txin . prevout . n ] . scriptPubKey ;
2016-03-31 05:51:29 -07:00
const CAmount & amount = coins - > vout [ txin . prevout . n ] . nValue ;
2012-05-31 13:01:16 -07:00
2016-03-31 05:54:58 -07:00
SignatureData sigdata ;
2012-08-20 11:06:27 -07:00
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if ( ! fHashSingle | | ( i < mergedTx . vout . size ( ) ) )
2018-02-01 17:49:42 -08:00
ProduceSignature ( MutableTransactionSignatureCreator ( & keystore , & mergedTx , i , amount , nHashType ) , prevPubKey , sigdata , consensusBranchId ) ;
2012-05-31 13:01:16 -07:00
// ... and merge in other signatures:
2014-06-25 18:09:36 -07:00
BOOST_FOREACH ( const CMutableTransaction & txv , txVariants ) {
2018-02-01 17:49:42 -08:00
sigdata = CombineSignatures ( prevPubKey , TransactionSignatureChecker ( & txConst , i , amount ) , sigdata , DataFromTransaction ( txv , i ) , consensusBranchId ) ;
2012-05-31 13:01:16 -07:00
}
2016-03-31 05:54:58 -07:00
UpdateTransaction ( mergedTx , i , sigdata ) ;
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 11:07:28 -07:00
ScriptError serror = SCRIPT_ERR_OK ;
2018-02-01 17:49:42 -08:00
if ( ! VerifyScript ( txin . scriptSig , prevPubKey , STANDARD_SCRIPT_VERIFY_FLAGS , TransactionSignatureChecker ( & txConst , i , amount ) , consensusBranchId , & 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 11:07:28 -07:00
TxInErrorToJSON ( txin , vErrors , ScriptErrorString ( serror ) ) ;
}
2012-05-31 13:01:16 -07: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 11:07:28 -07:00
bool fComplete = vErrors . empty ( ) ;
2012-05-31 13:01:16 -07:00
2015-05-10 05:48:35 -07:00
UniValue result ( UniValue : : VOBJ ) ;
2014-06-23 20:10:24 -07:00
result . push_back ( Pair ( " hex " , EncodeHexTx ( mergedTx ) ) ) ;
2012-05-31 13:01:16 -07:00
result . push_back ( Pair ( " 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 11:07:28 -07:00
if ( ! vErrors . empty ( ) ) {
result . push_back ( Pair ( " errors " , vErrors ) ) ;
}
2012-05-31 13:01:16 -07:00
return result ;
}
2015-05-18 05:02:18 -07:00
UniValue sendrawtransaction ( const UniValue & params , bool fHelp )
2012-05-31 13:01:16 -07:00
{
2013-08-28 15:41:46 -07:00
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 2 )
2012-05-31 13:01:16 -07:00
throw runtime_error (
2013-10-29 04:29:44 -07: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 \" " )
) ;
2014-10-19 01:46:17 -07:00
LOCK ( cs_main ) ;
2014-08-20 12:15:16 -07:00
RPCTypeCheck ( params , boost : : assign : : list_of ( UniValue : : VSTR ) ( UniValue : : VBOOL ) ) ;
2012-05-31 13:01:16 -07:00
// parse hex string from parameter
CTransaction tx ;
2014-06-23 20:10:24 -07:00
if ( ! DecodeHexTx ( tx , params [ 0 ] . get_str ( ) ) )
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " TX decode failed " ) ;
2016-08-30 12:49:38 -07:00
uint256 hashTx = tx . GetHash ( ) ;
2012-05-31 13:01:16 -07:00
2013-08-28 15:41:46 -07:00
bool fOverrideFees = false ;
if ( params . size ( ) > 1 )
fOverrideFees = params [ 1 ] . get_bool ( ) ;
2012-07-06 07:33:34 -07:00
CCoinsViewCache & view = * pcoinsTip ;
2014-09-02 12:21:15 -07:00
const CCoins * existingCoins = view . AccessCoins ( hashTx ) ;
2014-02-22 03:02:42 -08:00
bool fHaveMempool = mempool . exists ( hashTx ) ;
2014-09-02 12:21:15 -07:00
bool fHaveChain = existingCoins & & existingCoins - > nHeight < 1000000000 ;
2014-02-22 03:02:42 -08:00
if ( ! fHaveMempool & & ! fHaveChain ) {
// push to local node and sync with wallets
CValidationState state ;
2014-12-03 05:13:09 -08:00
bool fMissingInputs ;
if ( ! AcceptToMemoryPool ( mempool , state , tx , false , & fMissingInputs , ! fOverrideFees ) ) {
if ( state . IsInvalid ( ) ) {
2014-02-22 03:02:42 -08:00
throw JSONRPCError ( RPC_TRANSACTION_REJECTED , strprintf ( " %i: %s " , state . GetRejectCode ( ) , state . GetRejectReason ( ) ) ) ;
2014-12-03 05:13:09 -08:00
} else {
if ( fMissingInputs ) {
throw JSONRPCError ( RPC_TRANSACTION_ERROR , " Missing inputs " ) ;
}
2014-02-22 03:02:42 -08:00
throw JSONRPCError ( RPC_TRANSACTION_ERROR , state . GetRejectReason ( ) ) ;
2014-12-03 05:13:09 -08: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 09:54:00 -07:00
}
2014-02-22 03:02:42 -08:00
} else if ( fHaveChain ) {
throw JSONRPCError ( RPC_TRANSACTION_ALREADY_IN_CHAIN , " transaction already in block chain " ) ;
2012-07-12 16:46:24 -07:00
}
2014-06-09 01:02:00 -07:00
RelayTransaction ( tx ) ;
2012-05-31 13:01:16 -07:00
2012-07-12 16:46:24 -07:00
return hashTx . GetHex ( ) ;
2012-05-31 13:01:16 -07:00
}
2016-03-29 10:43:02 -07:00
static const CRPCCommand commands [ ] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
{ " rawtransactions " , " getrawtransaction " , & getrawtransaction , true } ,
{ " rawtransactions " , " createrawtransaction " , & createrawtransaction , true } ,
{ " rawtransactions " , " decoderawtransaction " , & decoderawtransaction , true } ,
{ " rawtransactions " , " decodescript " , & decodescript , true } ,
{ " rawtransactions " , " sendrawtransaction " , & sendrawtransaction , false } ,
{ " rawtransactions " , " signrawtransaction " , & signrawtransaction , false } , /* uses wallet if enabled */
{ " blockchain " , " gettxoutproof " , & gettxoutproof , true } ,
{ " blockchain " , " verifytxoutproof " , & verifytxoutproof , true } ,
} ;
void RegisterRawTransactionRPCCommands ( CRPCTable & tableRPC )
{
for ( unsigned int vcidx = 0 ; vcidx < ARRAYLEN ( commands ) ; vcidx + + )
tableRPC . appendCommand ( commands [ vcidx ] . name , & commands [ vcidx ] ) ;
}