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 } ,... ] } ```
This commit is contained in:
parent
f0c4281f84
commit
8ac2a4e178
1 changed files with 38 additions and 7 deletions
|
@ -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)
|
||||||
|
|
||||||
"\nResult:\n"
|
"\nResult:\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"
|
||||||
|
|
||||||
"\nExamples:\n"
|
"\nExamples:\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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue