aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rwxr-xr-xqa/rpc-tests/test_framework.py8
-rw-r--r--src/Makefile.am3
-rw-r--r--src/qt/forms/coincontroldialog.ui12
-rw-r--r--src/rest.cpp206
-rw-r--r--src/rpcserver.cpp7
-rw-r--r--src/rpcserver.h6
-rw-r--r--src/rpcwallet.cpp4
-rw-r--r--src/script/interpreter.cpp297
-rw-r--r--src/script/interpreter.h6
-rw-r--r--src/script/script_error.cpp67
-rw-r--r--src/script/script_error.h53
-rw-r--r--src/test/multisig_tests.cpp37
-rw-r--r--src/test/script_P2SH_tests.cpp19
-rw-r--r--src/test/script_tests.cpp66
-rw-r--r--src/test/transaction_tests.cpp10
-rw-r--r--src/txmempool.cpp38
-rw-r--r--src/txmempool.h44
-rw-r--r--src/util.cpp48
-rw-r--r--src/util.h37
-rw-r--r--src/utilmoneystr.cpp2
-rw-r--r--src/utilmoneystr.h2
-rw-r--r--src/utilstrencodings.cpp8
-rw-r--r--src/utilstrencodings.h9
-rw-r--r--src/utiltime.cpp13
-rw-r--r--src/utiltime.h2
26 files changed, 752 insertions, 254 deletions
diff --git a/.travis.yml b/.travis.yml
index f6b011ee1c..567428daf9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -40,7 +40,7 @@ matrix:
env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui" MAKEJOBS="-j2"
install:
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi
- - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-upgrade -qq $PACKAGES; fi
+ - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi
before_script:
- unset CC; unset CXX
- mkdir -p depends/SDKs depends/sdk-sources
diff --git a/qa/rpc-tests/test_framework.py b/qa/rpc-tests/test_framework.py
index c3396a5a83..9591c024fb 100755
--- a/qa/rpc-tests/test_framework.py
+++ b/qa/rpc-tests/test_framework.py
@@ -44,8 +44,8 @@ class BitcoinTestFramework(object):
# on outward. This ensures that chains are properly reorganised.
if not split:
connect_nodes_bi(self.nodes, 1, 2)
- sync_blocks(self.nodes[1:2])
- sync_mempools(self.nodes[1:2])
+ sync_blocks(self.nodes[1:3])
+ sync_mempools(self.nodes[1:3])
connect_nodes_bi(self.nodes, 0, 1)
connect_nodes_bi(self.nodes, 2, 3)
@@ -63,9 +63,9 @@ class BitcoinTestFramework(object):
def sync_all(self):
if self.is_network_split:
- sync_blocks(self.nodes[:1])
+ sync_blocks(self.nodes[:2])
sync_blocks(self.nodes[2:])
- sync_mempools(self.nodes[:1])
+ sync_mempools(self.nodes[:2])
sync_mempools(self.nodes[2:])
else:
sync_blocks(self.nodes)
diff --git a/src/Makefile.am b/src/Makefile.am
index 8b5d009842..3da833d733 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -112,6 +112,7 @@ BITCOIN_CORE_H = \
script/sigcache.h \
script/sign.h \
script/standard.h \
+ script/script_error.h \
serialize.h \
streams.h \
sync.h \
@@ -165,6 +166,7 @@ libbitcoin_server_a_SOURCES = \
net.cpp \
noui.cpp \
pow.cpp \
+ rest.cpp \
rpcblockchain.cpp \
rpcmining.cpp \
rpcmisc.cpp \
@@ -235,6 +237,7 @@ libbitcoin_common_a_SOURCES = \
script/script.cpp \
script/sign.cpp \
script/standard.cpp \
+ script/script_error.cpp \
$(BITCOIN_CORE_H)
# util: shared between all executables.
diff --git a/src/qt/forms/coincontroldialog.ui b/src/qt/forms/coincontroldialog.ui
index cbe58fec65..c1fef6b9b1 100644
--- a/src/qt/forms/coincontroldialog.ui
+++ b/src/qt/forms/coincontroldialog.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>Coin Control Address Selection</string>
+ <string>Coin Selection</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@@ -379,9 +379,6 @@
<property name="text">
<string>Tree mode</string>
</property>
- <property name="checked">
- <bool>true</bool>
- </property>
</widget>
</item>
<item>
@@ -395,6 +392,9 @@
<property name="text">
<string>List mode</string>
</property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item>
@@ -451,12 +451,12 @@
</column>
<column>
<property name="text">
- <string notr="true">Label</string>
+ <string>Received with label</string>
</property>
</column>
<column>
<property name="text">
- <string>Address</string>
+ <string>Received with address</string>
</property>
</column>
<column>
diff --git a/src/rest.cpp b/src/rest.cpp
new file mode 100644
index 0000000000..9a8793a517
--- /dev/null
+++ b/src/rest.cpp
@@ -0,0 +1,206 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <boost/algorithm/string.hpp>
+#include "rpcserver.h"
+#include "streams.h"
+#include "utilstrencodings.h"
+#include "core/block.h"
+#include "core/transaction.h"
+#include "version.h"
+#include "main.h"
+#include "sync.h"
+
+using namespace std;
+using namespace json_spirit;
+
+enum RetFormat {
+ RF_BINARY,
+ RF_HEX,
+ RF_JSON,
+};
+
+static const struct {
+ enum RetFormat rf;
+ const char *name;
+} rf_names[] = {
+ { RF_BINARY, "binary" }, // default, if match not found
+ { RF_HEX, "hex" },
+ { RF_JSON, "json" },
+};
+
+class RestErr {
+public:
+ enum HTTPStatusCode status;
+ string message;
+};
+
+extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
+extern Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex);
+
+static RestErr RESTERR(enum HTTPStatusCode status, string message)
+{
+ RestErr re;
+ re.status = status;
+ re.message = message;
+ return re;
+}
+
+static enum RetFormat ParseDataFormat(const string& format)
+{
+ for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
+ if (format == rf_names[i].name)
+ return rf_names[i].rf;
+
+ return rf_names[0].rf;
+}
+
+static bool ParseHashStr(const string& strReq, uint256& v)
+{
+ if (!IsHex(strReq) || (strReq.size() != 64))
+ return false;
+
+ v.SetHex(strReq);
+ return true;
+}
+
+static bool rest_block(AcceptedConnection *conn,
+ string& strReq,
+ map<string, string>& mapHeaders,
+ bool fRun)
+{
+ vector<string> params;
+ boost::split(params, strReq, boost::is_any_of("/"));
+
+ enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string(""));
+
+ string hashStr = params[0];
+ uint256 hash;
+ if (!ParseHashStr(hashStr, hash))
+ throw RESTERR(HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
+
+ CBlock block;
+ CBlockIndex* pblockindex = NULL;
+ {
+ LOCK(cs_main);
+ if (mapBlockIndex.count(hash) == 0)
+ throw RESTERR(HTTP_NOT_FOUND, hashStr + " not found");
+
+ pblockindex = mapBlockIndex[hash];
+ if (!ReadBlockFromDisk(block, pblockindex))
+ throw RESTERR(HTTP_NOT_FOUND, hashStr + " not found");
+ }
+
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
+ ssBlock << block;
+
+ switch (rf) {
+ case RF_BINARY: {
+ string binaryBlock = ssBlock.str();
+ conn->stream() << HTTPReply(HTTP_OK, binaryBlock, fRun, true, "application/octet-stream") << binaryBlock << std::flush;
+ return true;
+ }
+
+ case RF_HEX: {
+ string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";;
+ conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
+ return true;
+ }
+
+ case RF_JSON: {
+ Object objBlock = blockToJSON(block, pblockindex);
+ string strJSON = write_string(Value(objBlock), false) + "\n";
+ conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
+ return true;
+ }
+ }
+
+ // not reached
+ return true; // continue to process further HTTP reqs on this cxn
+}
+
+static bool rest_tx(AcceptedConnection *conn,
+ string& strReq,
+ map<string, string>& mapHeaders,
+ bool fRun)
+{
+ vector<string> params;
+ boost::split(params, strReq, boost::is_any_of("/"));
+
+ enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string(""));
+
+ string hashStr = params[0];
+ uint256 hash;
+ if (!ParseHashStr(hashStr, hash))
+ throw RESTERR(HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
+
+ CTransaction tx;
+ uint256 hashBlock = 0;
+ if (!GetTransaction(hash, tx, hashBlock, true))
+ throw RESTERR(HTTP_NOT_FOUND, hashStr + " not found");
+
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << tx;
+
+ switch (rf) {
+ case RF_BINARY: {
+ string binaryTx = ssTx.str();
+ conn->stream() << HTTPReply(HTTP_OK, binaryTx, fRun, true, "application/octet-stream") << binaryTx << std::flush;
+ return true;
+ }
+
+ case RF_HEX: {
+ string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";;
+ conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
+ return true;
+ }
+
+ case RF_JSON: {
+ Object objTx;
+ TxToJSON(tx, hashBlock, objTx);
+ string strJSON = write_string(Value(objTx), false) + "\n";
+ conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
+ return true;
+ }
+ }
+
+ // not reached
+ return true; // continue to process further HTTP reqs on this cxn
+}
+
+static const struct {
+ const char *prefix;
+ bool (*handler)(AcceptedConnection *conn,
+ string& strURI,
+ map<string, string>& mapHeaders,
+ bool fRun);
+} uri_prefixes[] = {
+ { "/rest/tx/", rest_tx },
+ { "/rest/block/", rest_block },
+};
+
+bool HTTPReq_REST(AcceptedConnection *conn,
+ string& strURI,
+ map<string, string>& mapHeaders,
+ bool fRun)
+{
+ try {
+ for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++) {
+ unsigned int plen = strlen(uri_prefixes[i].prefix);
+ if (strURI.substr(0, plen) == uri_prefixes[i].prefix) {
+ string strReq = strURI.substr(plen);
+ return uri_prefixes[i].handler(conn, strReq, mapHeaders, fRun);
+ }
+ }
+ }
+ catch (RestErr& re) {
+ conn->stream() << HTTPReply(re.status, re.message + "\r\n", false, false, "text/plain") << std::flush;
+ return false;
+ }
+
+ conn->stream() << HTTPError(HTTP_NOT_FOUND, false) << std::flush;
+ return false;
+}
+
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 709e9e9402..01005c1cee 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -947,9 +947,16 @@ void ServiceConnection(AcceptedConnection *conn)
if (mapHeaders["connection"] == "close")
fRun = false;
+ // Process via JSON-RPC API
if (strURI == "/") {
if (!HTTPReq_JSONRPC(conn, strRequest, mapHeaders, fRun))
break;
+
+ // Process via HTTP REST API
+ } else if (strURI.substr(0, 6) == "/rest/") {
+ if (!HTTPReq_REST(conn, strURI, mapHeaders, fRun))
+ break;
+
} else {
conn->stream() << HTTPError(HTTP_NOT_FOUND, false) << std::flush;
break;
diff --git a/src/rpcserver.h b/src/rpcserver.h
index 9a0681bfa3..b3234f65f2 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -219,4 +219,10 @@ extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp)
extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp);
+// in rest.cpp
+extern bool HTTPReq_REST(AcceptedConnection *conn,
+ std::string& strURI,
+ std::map<std::string, std::string>& mapHeaders,
+ bool fRun);
+
#endif // BITCOIN_RPCSERVER_H
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index f2b5e2061e..4d9e5ea137 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -1067,7 +1067,7 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
"\nList balances by receiving address.\n"
"\nArguments:\n"
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
- "2. includeempty (numeric, optional, dafault=false) Whether to include addresses that haven't received any payments.\n"
+ "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
"3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
"\nResult:\n"
@@ -1335,7 +1335,7 @@ Value listaccounts(const Array& params, bool fHelp)
"listaccounts ( minconf includeWatchonly)\n"
"\nReturns Object that has account names as keys, account balances as values.\n"
"\nArguments:\n"
- "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n"
+ "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
"2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
"\nResult:\n"
"{ (json object where keys are account names, and values are numeric balances\n"
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 5fda6248c2..cf81fe30a2 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -13,7 +13,6 @@
#include "pubkey.h"
#include "script/script.h"
#include "uint256.h"
-#include "util.h"
using namespace std;
@@ -26,6 +25,24 @@ static const CScriptNum bnOne(1);
static const CScriptNum bnFalse(0);
static const CScriptNum bnTrue(1);
+namespace {
+
+inline bool set_success(ScriptError* ret)
+{
+ if (ret)
+ *ret = SCRIPT_ERR_OK;
+ return true;
+}
+
+inline bool set_error(ScriptError* ret, const ScriptError serror)
+{
+ if (ret)
+ *ret = serror;
+ return false;
+}
+
+} // anon namespace
+
bool CastToBool(const valtype& vch)
{
for (unsigned int i = 0; i < vch.size(); i++)
@@ -55,16 +72,23 @@ static inline void popstack(vector<valtype>& stack)
}
bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
- if (vchPubKey.size() < 33)
- return error("Non-canonical public key: too short");
+ if (vchPubKey.size() < 33) {
+ // Non-canonical public key: too short
+ return false;
+ }
if (vchPubKey[0] == 0x04) {
- if (vchPubKey.size() != 65)
- return error("Non-canonical public key: invalid length for uncompressed key");
+ if (vchPubKey.size() != 65) {
+ // Non-canonical public key: invalid length for uncompressed key
+ return false;
+ }
} else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) {
- if (vchPubKey.size() != 33)
- return error("Non-canonical public key: invalid length for compressed key");
+ if (vchPubKey.size() != 33) {
+ // Non-canonical public key: invalid length for compressed key
+ return false;
+ }
} else {
- return error("Non-canonical public key: neither compressed nor uncompressed");
+ // Non-canonical public key: neither compressed nor uncompressed
+ return false;
}
return true;
}
@@ -79,47 +103,74 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
*/
bool static IsDERSignature(const valtype &vchSig) {
- if (vchSig.size() < 9)
- return error("Non-canonical signature: too short");
- if (vchSig.size() > 73)
- return error("Non-canonical signature: too long");
- if (vchSig[0] != 0x30)
- return error("Non-canonical signature: wrong type");
- if (vchSig[1] != vchSig.size()-3)
- return error("Non-canonical signature: wrong length marker");
+ if (vchSig.size() < 9) {
+ // Non-canonical signature: too short
+ return false;
+ }
+ if (vchSig.size() > 73) {
+ // Non-canonical signature: too long
+ return false;
+ }
+ if (vchSig[0] != 0x30) {
+ // Non-canonical signature: wrong type
+ return false;
+ }
+ if (vchSig[1] != vchSig.size()-3) {
+ // Non-canonical signature: wrong length marker
+ return false;
+ }
unsigned int nLenR = vchSig[3];
- if (5 + nLenR >= vchSig.size())
- return error("Non-canonical signature: S length misplaced");
+ if (5 + nLenR >= vchSig.size()) {
+ // Non-canonical signature: S length misplaced
+ return false;
+ }
unsigned int nLenS = vchSig[5+nLenR];
- if ((unsigned long)(nLenR+nLenS+7) != vchSig.size())
- return error("Non-canonical signature: R+S length mismatch");
+ if ((unsigned long)(nLenR+nLenS+7) != vchSig.size()) {
+ // Non-canonical signature: R+S length mismatch
+ return false;
+ }
const unsigned char *R = &vchSig[4];
- if (R[-2] != 0x02)
- return error("Non-canonical signature: R value type mismatch");
- if (nLenR == 0)
- return error("Non-canonical signature: R length is zero");
- if (R[0] & 0x80)
- return error("Non-canonical signature: R value negative");
- if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80))
- return error("Non-canonical signature: R value excessively padded");
+ if (R[-2] != 0x02) {
+ // Non-canonical signature: R value type mismatch
+ return false;
+ }
+ if (nLenR == 0) {
+ // Non-canonical signature: R length is zero
+ return false;
+ }
+ if (R[0] & 0x80) {
+ // Non-canonical signature: R value negative
+ return false;
+ }
+ if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) {
+ // Non-canonical signature: R value excessively padded
+ return false;
+ }
const unsigned char *S = &vchSig[6+nLenR];
- if (S[-2] != 0x02)
- return error("Non-canonical signature: S value type mismatch");
- if (nLenS == 0)
- return error("Non-canonical signature: S length is zero");
- if (S[0] & 0x80)
- return error("Non-canonical signature: S value negative");
- if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80))
- return error("Non-canonical signature: S value excessively padded");
-
+ if (S[-2] != 0x02) {
+ // Non-canonical signature: S value type mismatch
+ return false;
+ }
+ if (nLenS == 0) {
+ // Non-canonical signature: S length is zero
+ return false;
+ }
+ if (S[0] & 0x80) {
+ // Non-canonical signature: S value negative
+ return false;
+ }
+ if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) {
+ // Non-canonical signature: S value excessively padded
+ return false;
+ }
return true;
}
-bool static IsLowDERSignature(const valtype &vchSig) {
+bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
if (!IsDERSignature(vchSig)) {
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_DER);
}
unsigned int nLenR = vchSig[3];
unsigned int nLenS = vchSig[5+nLenR];
@@ -128,7 +179,7 @@ bool static IsLowDERSignature(const valtype &vchSig) {
// complement modulo the order could have been used instead, which is
// one byte shorter when encoded correctly.
if (!eccrypto::CheckSignatureElement(S, nLenS, true))
- return error("Non-canonical signature: S value is unnecessarily high");
+ return set_error(serror, SCRIPT_ERR_SIG_HIGH_S);
return true;
}
@@ -139,18 +190,19 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
}
unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
- return error("Non-canonical signature: unknown hashtype byte");
+ return false;
return true;
}
-bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags) {
+bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) {
- return false;
- } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig)) {
+ return set_error(serror, SCRIPT_ERR_SIG_DER);
+ } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {
+ // serror is set
return false;
} else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) {
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
}
return true;
}
@@ -185,7 +237,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
return true;
}
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker)
+bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
CScript::const_iterator pc = script.begin();
CScript::const_iterator pend = script.end();
@@ -194,8 +246,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
valtype vchPushValue;
vector<bool> vfExec;
vector<valtype> altstack;
+ set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if (script.size() > 10000)
- return false;
+ return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);
int nOpCount = 0;
bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0;
@@ -209,13 +262,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// Read instruction
//
if (!script.GetOp(pc, opcode, vchPushValue))
- return false;
+ return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE)
- return false;
+ return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
// Note how OP_RESERVED does not count towards the opcode limit.
if (opcode > OP_16 && ++nOpCount > 201)
- return false;
+ return set_error(serror, SCRIPT_ERR_OP_COUNT);
if (opcode == OP_CAT ||
opcode == OP_SUBSTR ||
@@ -232,11 +285,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
opcode == OP_MOD ||
opcode == OP_LSHIFT ||
opcode == OP_RSHIFT)
- return false; // Disabled opcodes.
+ return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes.
if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) {
if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) {
- return false;
+ return set_error(serror, SCRIPT_ERR_MINIMALDATA);
}
stack.push_back(vchPushValue);
} else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
@@ -288,7 +341,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fExec)
{
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
valtype& vch = stacktop(-1);
fValue = CastToBool(vch);
if (opcode == OP_NOTIF)
@@ -302,7 +355,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_ELSE:
{
if (vfExec.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
vfExec.back() = !vfExec.back();
}
break;
@@ -310,7 +363,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_ENDIF:
{
if (vfExec.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
vfExec.pop_back();
}
break;
@@ -320,18 +373,18 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// (true -- ) or
// (false -- false) and return
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
bool fValue = CastToBool(stacktop(-1));
if (fValue)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_VERIFY);
}
break;
case OP_RETURN:
{
- return false;
+ return set_error(serror, SCRIPT_ERR_OP_RETURN);
}
break;
@@ -342,7 +395,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_TOALTSTACK:
{
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
altstack.push_back(stacktop(-1));
popstack(stack);
}
@@ -351,7 +404,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_FROMALTSTACK:
{
if (altstack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION);
stack.push_back(altstacktop(-1));
popstack(altstack);
}
@@ -361,7 +414,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- )
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
popstack(stack);
popstack(stack);
}
@@ -371,7 +424,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x1 x2 x1 x2)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-2);
valtype vch2 = stacktop(-1);
stack.push_back(vch1);
@@ -383,7 +436,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
if (stack.size() < 3)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-3);
valtype vch2 = stacktop(-2);
valtype vch3 = stacktop(-1);
@@ -397,7 +450,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
if (stack.size() < 4)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-4);
valtype vch2 = stacktop(-3);
stack.push_back(vch1);
@@ -409,7 +462,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
if (stack.size() < 6)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-6);
valtype vch2 = stacktop(-5);
stack.erase(stack.end()-6, stack.end()-4);
@@ -422,7 +475,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 x4 -- x3 x4 x1 x2)
if (stack.size() < 4)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
swap(stacktop(-4), stacktop(-2));
swap(stacktop(-3), stacktop(-1));
}
@@ -432,7 +485,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x - 0 | x x)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-1);
if (CastToBool(vch))
stack.push_back(vch);
@@ -451,7 +504,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x -- )
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
popstack(stack);
}
break;
@@ -460,7 +513,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x -- x x)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-1);
stack.push_back(vch);
}
@@ -470,7 +523,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x2)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
stack.erase(stack.end() - 2);
}
break;
@@ -479,7 +532,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x1 x2 x1)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-2);
stack.push_back(vch);
}
@@ -491,11 +544,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int n = CScriptNum(stacktop(-1), fRequireMinimal).getint();
popstack(stack);
if (n < 0 || n >= (int)stack.size())
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-n-1);
if (opcode == OP_ROLL)
stack.erase(stack.end()-n-1);
@@ -509,7 +562,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// x2 x1 x3 after first swap
// x2 x3 x1 after second swap
if (stack.size() < 3)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
swap(stacktop(-3), stacktop(-2));
swap(stacktop(-2), stacktop(-1));
}
@@ -519,7 +572,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x2 x1)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
swap(stacktop(-2), stacktop(-1));
}
break;
@@ -528,7 +581,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x2 x1 x2)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-1);
stack.insert(stack.end()-2, vch);
}
@@ -539,7 +592,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (in -- in size)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn(stacktop(-1).size());
stack.push_back(bn.getvch());
}
@@ -555,7 +608,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 - bool)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype& vch1 = stacktop(-2);
valtype& vch2 = stacktop(-1);
bool fEqual = (vch1 == vch2);
@@ -572,7 +625,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fEqual)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_EQUALVERIFY);
}
}
break;
@@ -590,7 +643,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (in -- out)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn(stacktop(-1), fRequireMinimal);
switch (opcode)
{
@@ -623,7 +676,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- out)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn1(stacktop(-2), fRequireMinimal);
CScriptNum bn2(stacktop(-1), fRequireMinimal);
CScriptNum bn(0);
@@ -659,7 +712,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (CastToBool(stacktop(-1)))
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_NUMEQUALVERIFY);
}
}
break;
@@ -668,7 +721,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x min max -- out)
if (stack.size() < 3)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn1(stacktop(-3), fRequireMinimal);
CScriptNum bn2(stacktop(-2), fRequireMinimal);
CScriptNum bn3(stacktop(-1), fRequireMinimal);
@@ -692,7 +745,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (in -- hash)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype& vch = stacktop(-1);
valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
if (opcode == OP_RIPEMD160)
@@ -722,7 +775,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (sig pubkey -- bool)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype& vchSig = stacktop(-2);
valtype& vchPubKey = stacktop(-1);
@@ -733,10 +786,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// Drop the signature, since there's no way for a signature to sign itself
scriptCode.FindAndDelete(CScript(vchSig));
- if (!CheckSignatureEncoding(vchSig, flags)) {
+ if (!CheckSignatureEncoding(vchSig, flags, serror)) {
+ //serror is set
return false;
}
-
bool fSuccess = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode);
popstack(stack);
@@ -747,7 +800,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fSuccess)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY);
}
}
break;
@@ -759,26 +812,26 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
int i = 1;
if ((int)stack.size() < i)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
if (nKeysCount < 0 || nKeysCount > 20)
- return false;
+ return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
nOpCount += nKeysCount;
if (nOpCount > 201)
- return false;
+ return set_error(serror, SCRIPT_ERR_OP_COUNT);
int ikey = ++i;
i += nKeysCount;
if ((int)stack.size() < i)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
if (nSigsCount < 0 || nSigsCount > nKeysCount)
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_COUNT);
int isig = ++i;
i += nSigsCount;
if ((int)stack.size() < i)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
// Subset of script starting at the most recent codeseparator
CScript scriptCode(pbegincodehash, pend);
@@ -796,7 +849,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
valtype& vchSig = stacktop(-isig);
valtype& vchPubKey = stacktop(-ikey);
- if (!CheckSignatureEncoding(vchSig, flags)) {
+ if (!CheckSignatureEncoding(vchSig, flags, serror)) {
+ // serror is set
return false;
}
@@ -827,9 +881,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// so optionally verify it is exactly equal to zero prior
// to removing it from the stack.
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size())
- return error("CHECKMULTISIG dummy argument not null");
+ return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY);
popstack(stack);
stack.push_back(fSuccess ? vchTrue : vchFalse);
@@ -839,29 +893,29 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fSuccess)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY);
}
}
break;
default:
- return false;
+ return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
}
// Size limits
if (stack.size() + altstack.size() > 1000)
- return false;
+ return set_error(serror, SCRIPT_ERR_STACK_SIZE);
}
}
catch (...)
{
- return false;
+ return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
}
if (!vfExec.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
- return true;
+ return set_success(serror);
}
namespace {
@@ -966,14 +1020,14 @@ public:
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
if (nIn >= txTo.vin.size()) {
- LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ // nIn out of range
return 1;
}
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
- LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nIn);
+ // nOut out of range
return 1;
}
}
@@ -1013,30 +1067,35 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec
return true;
}
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker)
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
+ set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
+
if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) {
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
}
vector<vector<unsigned char> > stack, stackCopy;
- if (!EvalScript(stack, scriptSig, flags, checker))
+ if (!EvalScript(stack, scriptSig, flags, checker, serror))
+ // serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
- if (!EvalScript(stack, scriptPubKey, flags, checker))
+ if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
+ // serror is set
return false;
if (stack.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
if (CastToBool(stack.back()) == false)
- return false;
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
// Additional validation for spend-to-script-hash transactions:
if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
{
- if (!scriptSig.IsPushOnly()) // scriptSig must be literals-only
- return false; // or validation fails
+ // scriptSig must be literals-only or validation fails
+ if (!scriptSig.IsPushOnly())
+ return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
// stackCopy cannot be empty here, because if it was the
// P2SH HASH <> EQUAL scriptPubKey would be evaluated with
@@ -1047,12 +1106,16 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stackCopy);
- if (!EvalScript(stackCopy, pubKey2, flags, checker))
+ if (!EvalScript(stackCopy, pubKey2, flags, checker, serror))
+ // serror is set
return false;
if (stackCopy.empty())
- return false;
- return CastToBool(stackCopy.back());
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (!CastToBool(stackCopy.back()))
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ else
+ return set_success(serror);
}
- return true;
+ return set_success(serror);
}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index ed899fc411..14cccc558f 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -6,6 +6,8 @@
#ifndef BITCOIN_SCRIPT_INTERPRETER_H
#define BITCOIN_SCRIPT_INTERPRETER_H
+#include "script_error.h"
+
#include <vector>
#include <stdint.h>
#include <string>
@@ -85,7 +87,7 @@ public:
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
};
-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker);
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker);
+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
#endif // BITCOIN_SCRIPT_INTERPRETER_H
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
new file mode 100644
index 0000000000..4a3df268ec
--- /dev/null
+++ b/src/script/script_error.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "script_error.h"
+
+const char* ScriptErrorString(const ScriptError serror)
+{
+ switch (serror)
+ {
+ case SCRIPT_ERR_OK:
+ return "No error";
+ case SCRIPT_ERR_EVAL_FALSE:
+ return "Script evaluated without error but finished with a false/empty top stack element";
+ case SCRIPT_ERR_VERIFY:
+ return "Script failed an OP_VERIFY operation";
+ case SCRIPT_ERR_EQUALVERIFY:
+ return "Script failed an OP_EQUALVERIFY operation";
+ case SCRIPT_ERR_CHECKMULTISIGVERIFY:
+ return "Script failed an OP_CHECKMULTISIGVERIFY operation";
+ case SCRIPT_ERR_CHECKSIGVERIFY:
+ return "Script failed an OP_CHECKSIGVERIFY operation";
+ case SCRIPT_ERR_NUMEQUALVERIFY:
+ return "Script failed an OP_NUMEQUALVERIFY operation";
+ case SCRIPT_ERR_SCRIPT_SIZE:
+ return "Script is too big";
+ case SCRIPT_ERR_PUSH_SIZE:
+ return "Push value size limit exceeded";
+ case SCRIPT_ERR_OP_COUNT:
+ return "Operation limit exceeded";
+ case SCRIPT_ERR_STACK_SIZE:
+ return "Stack size limit exceeded";
+ case SCRIPT_ERR_SIG_COUNT:
+ return "Signature count negative or greater than pubkey count";
+ case SCRIPT_ERR_PUBKEY_COUNT:
+ return "Pubkey count negative or limit exceeded";
+ case SCRIPT_ERR_BAD_OPCODE:
+ return "Opcode missing or not understood";
+ case SCRIPT_ERR_DISABLED_OPCODE:
+ return "Attempted to use a disabled opcode";
+ case SCRIPT_ERR_INVALID_STACK_OPERATION:
+ return "Operation not valid with the current stack size";
+ case SCRIPT_ERR_INVALID_ALTSTACK_OPERATION:
+ return "Operation not valid with the current altstack size";
+ case SCRIPT_ERR_OP_RETURN:
+ return "OP_RETURN was encountered";
+ case SCRIPT_ERR_UNBALANCED_CONDITIONAL:
+ return "Invalid OP_IF construction";
+ case SCRIPT_ERR_SIG_HASHTYPE:
+ return "Signature hash type missing or not understood";
+ case SCRIPT_ERR_SIG_DER:
+ return "Non-canonical DER signature";
+ case SCRIPT_ERR_MINIMALDATA:
+ return "Data push larger than necessary";
+ case SCRIPT_ERR_SIG_PUSHONLY:
+ return "Only non-push operators allowed in signatures";
+ case SCRIPT_ERR_SIG_HIGH_S:
+ return "Non-canonical signature: S value is unnecessarily high";
+ case SCRIPT_ERR_SIG_NULLDUMMY:
+ return "Dummy CHECKMULTISIG argument must be zero";
+ case SCRIPT_ERR_UNKNOWN_ERROR:
+ case SCRIPT_ERR_ERROR_COUNT:
+ default: break;
+ }
+ return "unknown error";
+}
diff --git a/src/script/script_error.h b/src/script/script_error.h
new file mode 100644
index 0000000000..ae6626b257
--- /dev/null
+++ b/src/script/script_error.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_SCRIPT_ERROR_H
+#define BITCOIN_SCRIPT_ERROR_H
+
+typedef enum ScriptError_t
+{
+ SCRIPT_ERR_OK = 0,
+ SCRIPT_ERR_UNKNOWN_ERROR,
+ SCRIPT_ERR_EVAL_FALSE,
+ SCRIPT_ERR_OP_RETURN,
+
+ /* Max sizes */
+ SCRIPT_ERR_SCRIPT_SIZE,
+ SCRIPT_ERR_PUSH_SIZE,
+ SCRIPT_ERR_OP_COUNT,
+ SCRIPT_ERR_STACK_SIZE,
+ SCRIPT_ERR_SIG_COUNT,
+ SCRIPT_ERR_PUBKEY_COUNT,
+
+ /* Failed verify operations */
+ SCRIPT_ERR_VERIFY,
+ SCRIPT_ERR_EQUALVERIFY,
+ SCRIPT_ERR_CHECKMULTISIGVERIFY,
+ SCRIPT_ERR_CHECKSIGVERIFY,
+ SCRIPT_ERR_NUMEQUALVERIFY,
+
+ /* Logical/Format/Canonical errors */
+ SCRIPT_ERR_BAD_OPCODE,
+ SCRIPT_ERR_DISABLED_OPCODE,
+ SCRIPT_ERR_INVALID_STACK_OPERATION,
+ SCRIPT_ERR_INVALID_ALTSTACK_OPERATION,
+ SCRIPT_ERR_UNBALANCED_CONDITIONAL,
+
+ /* BIP62 */
+ SCRIPT_ERR_SIG_HASHTYPE,
+ SCRIPT_ERR_SIG_DER,
+ SCRIPT_ERR_MINIMALDATA,
+ SCRIPT_ERR_SIG_PUSHONLY,
+ SCRIPT_ERR_SIG_HIGH_S,
+ SCRIPT_ERR_SIG_NULLDUMMY,
+
+ SCRIPT_ERR_ERROR_COUNT
+} ScriptError;
+
+#define SCRIPT_ERR_LAST SCRIPT_ERR_ERROR_COUNT
+
+const char* ScriptErrorString(const ScriptError error);
+
+#endif // BITCOIN_SCRIPT_ERROR_H
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index e9fc86779a..8d06caa147 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -6,6 +6,7 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "script/interpreter.h"
#include "script/sign.h"
#include "uint256.h"
@@ -46,6 +47,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
{
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
+ ScriptError err;
CKey key[4];
for (int i = 0; i < 4; i++)
key[i].MakeNewKey(true);
@@ -82,19 +84,22 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys.clear();
keys += key[0],key[1]; // magic operator+= from boost.assign
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK(VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)));
+ BOOST_CHECK(VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
for (int i = 0; i < 4; i++)
{
keys.clear();
keys += key[i];
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
keys.clear();
keys += key[1],key[i];
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
// Test a OR b:
@@ -104,16 +109,24 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys += key[i];
s = sign_multisig(a_or_b, keys, txTo[1], 0);
if (i == 0 || i == 1)
- BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)), strprintf("a|b: %d", i));
+ {
+ BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
else
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)), strprintf("a|b: %d", i));
+ {
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+ }
}
s.clear();
s << OP_0 << OP_0;
- BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
s.clear();
s << OP_0 << OP_1;
- BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
for (int i = 0; i < 4; i++)
@@ -123,9 +136,15 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys += key[i],key[j];
s = sign_multisig(escrow, keys, txTo[2], 0);
if (i < j && i < 3 && j < 3)
- BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0)), strprintf("escrow 1: %d %d", i, j));
+ {
+ BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
else
- BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0)), strprintf("escrow 2: %d %d", i, j));
+ {
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+ }
}
}
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index fcab652783..a969eefa05 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -6,6 +6,7 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "script/sign.h"
#ifdef ENABLE_WALLET
@@ -27,7 +28,7 @@ Serialize(const CScript& s)
}
static bool
-Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
+Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
{
// Create dummy to/from transactions:
CMutableTransaction txFrom;
@@ -42,7 +43,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = 1;
- return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, SignatureChecker(txTo, 0));
+ return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, SignatureChecker(txTo, 0), &err);
}
@@ -124,6 +125,7 @@ BOOST_AUTO_TEST_CASE(sign)
BOOST_AUTO_TEST_CASE(norecurse)
{
+ ScriptError err;
// Make sure only the outer pay-to-script-hash does the
// extra-validation thing:
CScript invalidAsScript;
@@ -135,7 +137,8 @@ BOOST_AUTO_TEST_CASE(norecurse)
scriptSig << Serialize(invalidAsScript);
// Should not verify, because it will try to execute OP_INVALIDOPCODE
- BOOST_CHECK(!Verify(scriptSig, p2sh, true));
+ BOOST_CHECK(!Verify(scriptSig, p2sh, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_BAD_OPCODE, ScriptErrorString(err));
// Try to recur, and verification should succeed because
// the inner HASH160 <> EQUAL should only check the hash:
@@ -143,7 +146,8 @@ BOOST_AUTO_TEST_CASE(norecurse)
CScript scriptSig2;
scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh);
- BOOST_CHECK(Verify(scriptSig2, p2sh2, true));
+ BOOST_CHECK(Verify(scriptSig2, p2sh2, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(set)
@@ -238,6 +242,7 @@ BOOST_AUTO_TEST_CASE(switchover)
{
// Test switch over code
CScript notValid;
+ ScriptError err;
notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
CScript scriptSig;
scriptSig << Serialize(notValid);
@@ -246,9 +251,11 @@ BOOST_AUTO_TEST_CASE(switchover)
// Validation should succeed under old rules (hash is correct):
- BOOST_CHECK(Verify(scriptSig, fund, false));
+ BOOST_CHECK(Verify(scriptSig, fund, false, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
// Fail under new:
- BOOST_CHECK(!Verify(scriptSig, fund, true));
+ BOOST_CHECK(!Verify(scriptSig, fund, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EQUALVERIFY, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(AreInputsStandard)
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index cff1664a1e..ede13b23c2 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -10,6 +10,7 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "script/sign.h"
#include "util.h"
@@ -92,7 +93,9 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message)
{
- BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)), 0)) == expect, message);
+ ScriptError err;
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)), 0), &err) == expect, message);
+ BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message);
}
void static NegateSignatureS(std::vector<unsigned char>& vchSig) {
@@ -590,20 +593,25 @@ BOOST_AUTO_TEST_CASE(script_PushData)
static const unsigned char pushdata2[] = { OP_PUSHDATA2, 1, 0, 0x5a };
static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a };
+ ScriptError err;
vector<vector<unsigned char> > directStack;
- BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), true, BaseSignatureChecker(), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata1Stack;
- BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), true, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata1Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata2Stack;
- BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), true, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata2Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata4Stack;
- BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), true, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata4Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
CScript
@@ -640,6 +648,7 @@ sign_multisig(CScript scriptPubKey, const CKey &key, CTransaction transaction)
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
{
+ ScriptError err;
CKey key1, key2, key3;
key1.MakeNewKey(true);
key2.MakeNewKey(false);
@@ -652,19 +661,24 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
txTo12.vout[0].nValue = 2;
- BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
{
+ ScriptError err;
CKey key1, key2, key3, key4;
key1.MakeNewKey(true);
key2.MakeNewKey(false);
@@ -680,46 +694,55 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
std::vector<CKey> keys;
keys.push_back(key1); keys.push_back(key2);
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key3);
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key3);
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear(); // Must have signatures
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(script_combineSigs)
@@ -833,11 +856,13 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
BOOST_AUTO_TEST_CASE(script_standard_push)
{
+ ScriptError err;
for (int i=0; i<67000; i++) {
CScript script;
script << i;
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Number " << i << " is not pure push.");
- BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker()), "Number " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
for (unsigned int i=0; i<=MAX_SCRIPT_ELEMENT_SIZE; i++) {
@@ -845,7 +870,8 @@ BOOST_AUTO_TEST_CASE(script_standard_push)
CScript script;
script << data;
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Length " << i << " is not pure push.");
- BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker()), "Length " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
}
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index d4c9b1a0ea..bf3a60c04f 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -10,6 +10,7 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "core_io.h"
#include <map>
@@ -86,6 +87,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
Array tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
+ ScriptError err;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
@@ -142,8 +144,9 @@ BOOST_AUTO_TEST_CASE(tx_valid)
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, SignatureChecker(tx, i)),
+ verify_flags, SignatureChecker(tx, i), &err),
strTest);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
}
}
@@ -160,6 +163,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
Array tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
+ ScriptError err;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
@@ -215,10 +219,10 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, SignatureChecker(tx, i));
+ verify_flags, SignatureChecker(tx, i), &err);
}
-
BOOST_CHECK_MESSAGE(!fValid, strTest);
+ BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err));
}
}
}
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index b5070d5104..e13f1cc350 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2013 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "txmempool.h"
@@ -45,9 +45,9 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
return dResult;
}
-//
-// Keep track of fee/priority for transactions confirmed within N blocks
-//
+/**
+ * Keep track of fee/priority for transactions confirmed within N blocks
+ */
class CBlockAverage
{
private:
@@ -86,8 +86,10 @@ public:
return prioritySamples.size();
}
- // Used as belt-and-suspenders check when reading to detect
- // file corruption
+ /**
+ * Used as belt-and-suspenders check when reading to detect
+ * file corruption
+ */
bool AreSane(const std::vector<CFeeRate>& vecFee, const CFeeRate& minRelayFee)
{
BOOST_FOREACH(CFeeRate fee, vecFee)
@@ -139,16 +141,20 @@ public:
class CMinerPolicyEstimator
{
private:
- // Records observed averages transactions that confirmed within one block, two blocks,
- // three blocks etc.
+ /**
+ * Records observed averages transactions that confirmed within one block, two blocks,
+ * three blocks etc.
+ */
std::vector<CBlockAverage> history;
std::vector<CFeeRate> sortedFeeSamples;
std::vector<double> sortedPrioritySamples;
int nBestSeenHeight;
- // nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
- // nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
+ /**
+ * nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
+ * nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
+ */
void seenTxConfirm(const CFeeRate& feeRate, const CFeeRate& minRelayFee, double dPriority, int nBlocksAgo)
{
// Last entry records "everything else".
@@ -248,7 +254,9 @@ public:
}
}
- // Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
+ /**
+ * Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
+ */
CFeeRate estimateFee(int nBlocksToConfirm)
{
nBlocksToConfirm--;
@@ -332,7 +340,7 @@ public:
size_t numEntries;
filein >> numEntries;
if (numEntries <= 0 || numEntries > 10000)
- throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entires.");
+ throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entries.");
std::vector<CBlockAverage> fileHistory;
@@ -462,7 +470,9 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
}
}
-// Called when a block is connected. Removes from mempool and updates the miner fee estimator.
+/**
+ * Called when a block is connected. Removes from mempool and updates the miner fee estimator.
+ */
void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
std::list<CTransaction>& conflicts)
{
diff --git a/src/txmempool.h b/src/txmempool.h
index 2ec80cb860..0d3c8bba6a 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2013 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_TXMEMPOOL_H
@@ -25,19 +25,19 @@ inline bool AllowFree(double dPriority)
/** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
-/*
+/**
* CTxMemPool stores these:
*/
class CTxMemPoolEntry
{
private:
CTransaction tx;
- CAmount nFee; // Cached to avoid expensive parent-transaction lookups
- size_t nTxSize; // ... and avoid recomputing tx size
- size_t nModSize; // ... and modified size for priority
- int64_t nTime; // Local time when entering the mempool
- double dPriority; // Priority when entering the mempool
- unsigned int nHeight; // Chain height when entering the mempool
+ CAmount nFee; //! Cached to avoid expensive parent-transaction lookups
+ size_t nTxSize; //! ... and avoid recomputing tx size
+ size_t nModSize; //! ... and modified size for priority
+ int64_t nTime; //! Local time when entering the mempool
+ double dPriority; //! Priority when entering the mempool
+ unsigned int nHeight; //! Chain height when entering the mempool
public:
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
@@ -68,7 +68,7 @@ public:
bool IsNull() const { return (ptx == NULL && n == (uint32_t) -1); }
};
-/*
+/**
* CTxMemPool stores valid-according-to-the-current-best-chain
* transactions that may be included in the next block.
*
@@ -81,12 +81,12 @@ public:
class CTxMemPool
{
private:
- bool fSanityCheck; // Normally false, true if -checkmempool or -regtest
+ bool fSanityCheck; //! Normally false, true if -checkmempool or -regtest
unsigned int nTransactionsUpdated;
CMinerPolicyEstimator* minerPolicyEstimator;
- CFeeRate minRelayFee; // Passed to constructor to avoid dependency on main
- uint64_t totalTxSize; // sum of all mempool tx' byte sizes
+ CFeeRate minRelayFee; //! Passed to constructor to avoid dependency on main
+ uint64_t totalTxSize; //! sum of all mempool tx' byte sizes
public:
mutable CCriticalSection cs;
@@ -97,7 +97,7 @@ public:
CTxMemPool(const CFeeRate& _minRelayFee);
~CTxMemPool();
- /*
+ /**
* If sanity-checking is turned on, check makes sure the pool is
* consistent (does not contain two transactions that spend the same inputs,
* all inputs are in the mapNextTx array). If sanity-checking is turned off,
@@ -141,19 +141,21 @@ public:
bool lookup(uint256 hash, CTransaction& result) const;
- // Estimate fee rate needed to get into the next
- // nBlocks
+ /** Estimate fee rate needed to get into the next nBlocks */
CFeeRate estimateFee(int nBlocks) const;
- // Estimate priority needed to get into the next
- // nBlocks
+
+ /** Estimate priority needed to get into the next nBlocks */
double estimatePriority(int nBlocks) const;
- // Write/Read estimates to disk
+
+ /** Write/Read estimates to disk */
bool WriteFeeEstimates(CAutoFile& fileout) const;
bool ReadFeeEstimates(CAutoFile& filein);
};
-/** CCoinsView that brings transactions from a memorypool into view.
- It does not check for spendings by memory pool transactions. */
+/**
+ * CCoinsView that brings transactions from a memorypool into view.
+ * It does not check for spendings by memory pool transactions.
+ */
class CCoinsViewMemPool : public CCoinsViewBacked
{
protected:
diff --git a/src/util.cpp b/src/util.cpp
index 0f5c036352..0cdf4e614d 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
#if defined(HAVE_CONFIG_H)
@@ -105,7 +105,7 @@ bool fLogTimestamps = false;
bool fLogIPs = false;
volatile bool fReopenDebugLog = false;
-// Init OpenSSL library multithreading support
+/** Init OpenSSL library multithreading support */
static CCriticalSection** ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line)
{
@@ -149,18 +149,22 @@ public:
}
instance_of_cinit;
-// LogPrintf() has been broken a couple of times now
-// by well-meaning people adding mutexes in the most straightforward way.
-// It breaks because it may be called by global destructors during shutdown.
-// Since the order of destruction of static/global objects is undefined,
-// defining a mutex as a global object doesn't work (the mutex gets
-// destroyed, and then some later destructor calls OutputDebugStringF,
-// maybe indirectly, and you get a core dump at shutdown trying to lock
-// the mutex).
+/**
+ * LogPrintf() has been broken a couple of times now
+ * by well-meaning people adding mutexes in the most straightforward way.
+ * It breaks because it may be called by global destructors during shutdown.
+ * Since the order of destruction of static/global objects is undefined,
+ * defining a mutex as a global object doesn't work (the mutex gets
+ * destroyed, and then some later destructor calls OutputDebugStringF,
+ * maybe indirectly, and you get a core dump at shutdown trying to lock
+ * the mutex).
+ */
static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
-// We use boost::call_once() to make sure these are initialized
-// in a thread-safe manner the first time called:
+/**
+ * We use boost::call_once() to make sure these are initialized
+ * in a thread-safe manner the first time called:
+ */
static FILE* fileout = NULL;
static boost::mutex* mutexDebugLog = NULL;
@@ -500,9 +504,11 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
#endif /* WIN32 */
}
-// Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
-// Specifically handles case where path p exists, but it wasn't possible for the user to
-// write to the parent directory.
+/**
+ * Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
+ * Specifically handles case where path p exists, but it wasn't possible for the user to
+ * write to the parent directory.
+ */
bool TryCreateDirectory(const boost::filesystem::path& p)
{
try
@@ -542,8 +548,10 @@ bool TruncateFile(FILE *file, unsigned int length) {
#endif
}
-// this function tries to raise the file descriptor limit to the requested number.
-// It returns the actual file descriptor limit (which may be more or less than nMinFD)
+/**
+ * this function tries to raise the file descriptor limit to the requested number.
+ * It returns the actual file descriptor limit (which may be more or less than nMinFD)
+ */
int RaiseFileDescriptorLimit(int nMinFD) {
#if defined(WIN32)
return 2048;
@@ -563,8 +571,10 @@ int RaiseFileDescriptorLimit(int nMinFD) {
#endif
}
-// this function tries to make a particular range of a file allocated (corresponding to disk space)
-// it is advisory, and the range specified in the arguments will never contain live data
+/**
+ * this function tries to make a particular range of a file allocated (corresponding to disk space)
+ * it is advisory, and the range specified in the arguments will never contain live data
+ */
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
#if defined(WIN32)
// Windows-specific version
diff --git a/src/util.h b/src/util.h
index 4b2415278b..a4aaf29f91 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
/**
@@ -40,25 +40,26 @@ extern volatile bool fReopenDebugLog;
void SetupEnvironment();
-/* Return true if log accepts specified category */
+/** Return true if log accepts specified category */
bool LogAcceptCategory(const char* category);
-/* Send a string to the log output */
+/** Send a string to the log output */
int LogPrintStr(const std::string &str);
#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__)
-/* When we switch to C++11, this can be switched to variadic templates instead
+/**
+ * When we switch to C++11, this can be switched to variadic templates instead
* of this macro-based construction (see tinyformat.h).
*/
#define MAKE_ERROR_AND_LOG_FUNC(n) \
- /* Print to debug.log if -debug=category switch is given OR category is NULL. */ \
+ /** Print to debug.log if -debug=category switch is given OR category is NULL. */ \
template<TINYFORMAT_ARGTYPES(n)> \
static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \
{ \
if(!LogAcceptCategory(category)) return 0; \
return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \
} \
- /* Log error and return false */ \
+ /** Log error and return false */ \
template<TINYFORMAT_ARGTYPES(n)> \
static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \
{ \
@@ -68,7 +69,8 @@ int LogPrintStr(const std::string &str);
TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC)
-/* Zero-arg versions of logging and error, these are not covered by
+/**
+ * Zero-arg versions of logging and error, these are not covered by
* TINYFORMAT_FOREACH_ARGNUM
*/
static inline int LogPrint(const char* category, const char* format)
@@ -162,13 +164,15 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue);
void SetThreadPriority(int nPriority);
void RenameThread(const char* name);
-// Standard wrapper for do-something-forever thread functions.
-// "Forever" really means until the thread is interrupted.
-// Use it like:
-// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000));
-// or maybe:
-// boost::function<void()> f = boost::bind(&FunctionWithArg, argument);
-// threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds));
+/**
+ * Standard wrapper for do-something-forever thread functions.
+ * "Forever" really means until the thread is interrupted.
+ * Use it like:
+ * new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000));
+ * or maybe:
+ * boost::function<void()> f = boost::bind(&FunctionWithArg, argument);
+ * threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds));
+ */
template <typename Callable> void LoopForever(const char* name, Callable func, int64_t msecs)
{
std::string s = strprintf("bitcoin-%s", name);
@@ -196,7 +200,10 @@ template <typename Callable> void LoopForever(const char* name, Callable func,
throw;
}
}
-// .. and a wrapper that just calls func once
+
+/**
+ * .. and a wrapper that just calls func once
+ */
template <typename Callable> void TraceThread(const char* name, Callable func)
{
std::string s = strprintf("bitcoin-%s", name);
diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp
index 267a5b845c..085adae85e 100644
--- a/src/utilmoneystr.cpp
+++ b/src/utilmoneystr.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
#include "utilmoneystr.h"
diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h
index 65415afd3f..6a153db5fa 100644
--- a/src/utilmoneystr.h
+++ b/src/utilmoneystr.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
/**
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
index 15094e5999..a961b3c5cd 100644
--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
#include "utilstrencodings.h"
@@ -14,8 +14,10 @@
using namespace std;
-// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
-// even possibly remotely dangerous like & or >
+/**
+ * safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
+ * even possibly remotely dangerous like & or >
+ */
static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@()");
string SanitizeString(const string& str)
{
diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h
index 0b8c1a1781..0c0171b894 100644
--- a/src/utilstrencodings.h
+++ b/src/utilstrencodings.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
/**
@@ -19,7 +19,7 @@
#define UEND(a) ((unsigned char*)&((&(a))[1]))
#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
-// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
+/** This is needed because the foreach macro can't get over the comma in pair<t1, t2> */
#define PAIRTYPE(t1, t2) std::pair<t1, t2>
std::string SanitizeString(const std::string& str);
@@ -45,7 +45,7 @@ int atoi(const std::string& str);
/**
* Convert string to signed 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
- * false if not the entire string could be parsed or when overflow or underflow occured.
+ * false if not the entire string could be parsed or when overflow or underflow occurred.
*/
bool ParseInt32(const std::string& str, int32_t *out);
@@ -74,7 +74,8 @@ inline std::string HexStr(const T& vch, bool fSpaces=false)
return HexStr(vch.begin(), vch.end(), fSpaces);
}
-/** Format a paragraph of text to a fixed width, adding spaces for
+/**
+ * Format a paragraph of text to a fixed width, adding spaces for
* indentation to any added line.
*/
std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0);
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index 78f0342cba..9c137e8aa0 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
#if defined(HAVE_CONFIG_H)
@@ -14,7 +14,7 @@
using namespace std;
-static int64_t nMockTime = 0; // For unit testing
+static int64_t nMockTime = 0; //! For unit testing
int64_t GetTime()
{
@@ -42,9 +42,12 @@ int64_t GetTimeMicros()
void MilliSleep(int64_t n)
{
-// Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
-// until fixed in 1.52. Use the deprecated sleep method for the broken case.
-// See: https://svn.boost.org/trac/boost/ticket/7238
+
+/**
+ * Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
+ * until fixed in 1.52. Use the deprecated sleep method for the broken case.
+ * See: https://svn.boost.org/trac/boost/ticket/7238
+ */
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
diff --git a/src/utiltime.h b/src/utiltime.h
index 6f82e5a836..9d7d42fe47 100644
--- a/src/utiltime.h
+++ b/src/utiltime.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 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.
#ifndef BITCOIN_UTILTIME_H