Skip to content

Commit 8ac2a4e

Browse files
committed
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 } ,... ] } ```
1 parent f0c4281 commit 8ac2a4e

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

src/rpcrawtransaction.cpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2010 Satoshi Nakamoto
2-
// Copyright (c) 2009-2014 The Bitcoin Core developers
2+
// Copyright (c) 2009-2015 The Bitcoin Core developers
33
// Distributed under the MIT software license, see the accompanying
44
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

@@ -13,6 +13,7 @@
1313
#include "net.h"
1414
#include "rpcserver.h"
1515
#include "script/script.h"
16+
#include "script/script_error.h"
1617
#include "script/sign.h"
1718
#include "script/standard.h"
1819
#include "uint256.h"
@@ -491,6 +492,18 @@ Value decodescript(const Array& params, bool fHelp)
491492
return r;
492493
}
493494

495+
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
496+
static void TxInErrorToJSON(const CTxIn& txin, Array& vErrorsRet, const std::string& strMessage)
497+
{
498+
Object entry;
499+
entry.push_back(Pair("txid", txin.prevout.hash.ToString()));
500+
entry.push_back(Pair("vout", (uint64_t)txin.prevout.n));
501+
entry.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
502+
entry.push_back(Pair("sequence", (uint64_t)txin.nSequence));
503+
entry.push_back(Pair("error", strMessage));
504+
vErrorsRet.push_back(entry);
505+
}
506+
494507
Value signrawtransaction(const Array& params, bool fHelp)
495508
{
496509
if (fHelp || params.size() < 1 || params.size() > 4)
@@ -532,8 +545,18 @@ Value signrawtransaction(const Array& params, bool fHelp)
532545

533546
"\nResult:\n"
534547
"{\n"
535-
" \"hex\": \"value\", (string) The raw transaction with signature(s) (hex-encoded string)\n"
536-
" \"complete\": true|false (boolean) if transaction has a complete set of signature\n"
548+
" \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
549+
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
550+
" \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
551+
" {\n"
552+
" \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
553+
" \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
554+
" \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
555+
" \"sequence\" : n, (numeric) Script sequence number\n"
556+
" \"error\" : \"text\" (string) Verification or signing error related to the input\n"
557+
" }\n"
558+
" ,...\n"
559+
" ]\n"
537560
"}\n"
538561

539562
"\nExamples:\n"
@@ -568,7 +591,6 @@ Value signrawtransaction(const Array& params, bool fHelp)
568591
// mergedTx will end up with all the signatures; it
569592
// starts as a clone of the rawtx:
570593
CMutableTransaction mergedTx(txVariants[0]);
571-
bool fComplete = true;
572594

573595
// Fetch previous transactions (inputs):
574596
CCoinsView viewDummy;
@@ -683,12 +705,15 @@ Value signrawtransaction(const Array& params, bool fHelp)
683705

684706
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
685707

708+
// Script verification errors
709+
Array vErrors;
710+
686711
// Sign what we can:
687712
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
688713
CTxIn& txin = mergedTx.vin[i];
689714
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
690715
if (coins == NULL || !coins->IsAvailable(txin.prevout.n)) {
691-
fComplete = false;
716+
TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
692717
continue;
693718
}
694719
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
@@ -702,13 +727,19 @@ Value signrawtransaction(const Array& params, bool fHelp)
702727
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
703728
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
704729
}
705-
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i)))
706-
fComplete = false;
730+
ScriptError serror = SCRIPT_ERR_OK;
731+
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i), &serror)) {
732+
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
733+
}
707734
}
735+
bool fComplete = vErrors.empty();
708736

709737
Object result;
710738
result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
711739
result.push_back(Pair("complete", fComplete));
740+
if (!vErrors.empty()) {
741+
result.push_back(Pair("errors", vErrors));
742+
}
712743

713744
return result;
714745
}

0 commit comments

Comments
 (0)