@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -13,6 +13,7 @@
# include "net.h"
# include "net.h"
# include "rpcserver.h"
# include "rpcserver.h"
# include "script/script.h"
# include "script/script.h"
# include "script/script_error.h"
# include "script/sign.h"
# include "script/sign.h"
# include "script/standard.h"
# include "script/standard.h"
# include "uint256.h"
# include "uint256.h"
@ -491,6 +492,18 @@ Value decodescript(const Array& params, bool fHelp)
return r ;
return r ;
}
}
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
static void TxInErrorToJSON ( const CTxIn & txin , Array & vErrorsRet , const std : : string & strMessage )
{
Object entry ;
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 ) ;
}
Value signrawtransaction ( const Array & params , bool fHelp )
Value signrawtransaction ( const Array & params , bool fHelp )
{
{
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 4 )
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 4 )
@ -532,8 +545,18 @@ Value signrawtransaction(const Array& params, bool fHelp)
" \n Result: \n "
" \n Result: \n "
" { \n "
" { \n "
" \" hex \" : \" value \" , (string) The raw transaction with signature(s) (hex-encoded string) \n "
" \" hex \" : \" value \" , (string) The hex-encoded raw transaction with signature(s) \n "
" \" complete \" : true|false (boolean) if transaction has a complete set of signature \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 "
" \n Examples: \n "
" \n Examples: \n "
@ -568,7 +591,6 @@ Value signrawtransaction(const Array& params, bool fHelp)
// mergedTx will end up with all the signatures; it
// mergedTx will end up with all the signatures; it
// starts as a clone of the rawtx:
// starts as a clone of the rawtx:
CMutableTransaction mergedTx ( txVariants [ 0 ] ) ;
CMutableTransaction mergedTx ( txVariants [ 0 ] ) ;
bool fComplete = true ;
// Fetch previous transactions (inputs):
// Fetch previous transactions (inputs):
CCoinsView viewDummy ;
CCoinsView viewDummy ;
@ -683,12 +705,15 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fHashSingle = ( ( nHashType & ~ SIGHASH_ANYONECANPAY ) = = SIGHASH_SINGLE ) ;
bool fHashSingle = ( ( nHashType & ~ SIGHASH_ANYONECANPAY ) = = SIGHASH_SINGLE ) ;
// Script verification errors
Array vErrors ;
// Sign what we can:
// Sign what we can:
for ( unsigned int i = 0 ; i < mergedTx . vin . size ( ) ; i + + ) {
for ( unsigned int i = 0 ; i < mergedTx . vin . size ( ) ; i + + ) {
CTxIn & txin = mergedTx . vin [ i ] ;
CTxIn & txin = mergedTx . vin [ i ] ;
const CCoins * coins = view . AccessCoins ( txin . prevout . hash ) ;
const CCoins * coins = view . AccessCoins ( txin . prevout . hash ) ;
if ( coins = = NULL | | ! coins - > IsAvailable ( txin . prevout . n ) ) {
if ( coins = = NULL | | ! coins - > IsAvailable ( txin . prevout . n ) ) {
fComplete = false ;
TxInErrorToJSON ( txin , vErrors , " Input not found or already spent " ) ;
continue ;
continue ;
}
}
const CScript & prevPubKey = coins - > vout [ txin . prevout . n ] . scriptPubKey ;
const CScript & prevPubKey = coins - > vout [ txin . prevout . n ] . scriptPubKey ;
@ -702,13 +727,19 @@ Value signrawtransaction(const Array& params, bool fHelp)
BOOST_FOREACH ( const CMutableTransaction & txv , txVariants ) {
BOOST_FOREACH ( const CMutableTransaction & txv , txVariants ) {
txin . scriptSig = CombineSignatures ( prevPubKey , mergedTx , i , txin . scriptSig , txv . vin [ i ] . scriptSig ) ;
txin . scriptSig = CombineSignatures ( prevPubKey , mergedTx , i , txin . scriptSig , txv . vin [ i ] . scriptSig ) ;
}
}
if ( ! VerifyScript ( txin . scriptSig , prevPubKey , STANDARD_SCRIPT_VERIFY_FLAGS , MutableTransactionSignatureChecker ( & mergedTx , i ) ) )
ScriptError serror = SCRIPT_ERR_OK ;
fComplete = false ;
if ( ! VerifyScript ( txin . scriptSig , prevPubKey , STANDARD_SCRIPT_VERIFY_FLAGS , MutableTransactionSignatureChecker ( & mergedTx , i ) , & serror ) ) {
TxInErrorToJSON ( txin , vErrors , ScriptErrorString ( serror ) ) ;
}
}
}
bool fComplete = vErrors . empty ( ) ;
Object result ;
Object result ;
result . push_back ( Pair ( " hex " , EncodeHexTx ( mergedTx ) ) ) ;
result . push_back ( Pair ( " hex " , EncodeHexTx ( mergedTx ) ) ) ;
result . push_back ( Pair ( " complete " , fComplete ) ) ;
result . push_back ( Pair ( " complete " , fComplete ) ) ;
if ( ! vErrors . empty ( ) ) {
result . push_back ( Pair ( " errors " , vErrors ) ) ;
}
return result ;
return result ;
}
}