Skip to content

Commit

Permalink
RPC: show script verification errors in "signrawtransaction" result
Browse files Browse the repository at this point in the history
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
    }
    ,...
  ]
}
```
  • Loading branch information
dexX7 committed May 5, 2015
1 parent f0c4281 commit 8ac2a4e
Showing 1 changed file with 38 additions and 7 deletions.
45 changes: 38 additions & 7 deletions src/rpcrawtransaction.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// 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
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand All @@ -13,6 +13,7 @@
#include "net.h"
#include "rpcserver.h"
#include "script/script.h"
#include "script/script_error.h"
#include "script/sign.h"
#include "script/standard.h"
#include "uint256.h"
Expand Down Expand Up @@ -491,6 +492,18 @@ Value decodescript(const Array& params, bool fHelp)
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)
{
if (fHelp || params.size() < 1 || params.size() > 4)
Expand Down Expand Up @@ -532,8 +545,18 @@ Value signrawtransaction(const Array& params, bool fHelp)

"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The raw transaction with signature(s) (hex-encoded string)\n"
" \"complete\": true|false (boolean) if transaction has a complete set of signature\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"

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

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

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

// Script verification errors
Array vErrors;

// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
if (coins == NULL || !coins->IsAvailable(txin.prevout.n)) {
fComplete = false;
TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
continue;
}
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
Expand All @@ -702,13 +727,19 @@ Value signrawtransaction(const Array& params, bool fHelp)
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i)))
fComplete = false;
ScriptError serror = SCRIPT_ERR_OK;
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i), &serror)) {
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
}
}
bool fComplete = vErrors.empty();

Object result;
result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
result.push_back(Pair("complete", fComplete));
if (!vErrors.empty()) {
result.push_back(Pair("errors", vErrors));
}

return result;
}
Expand Down

0 comments on commit 8ac2a4e

Please sign in to comment.