aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am13
-rw-r--r--src/alert.cpp4
-rw-r--r--src/alert.h2
-rw-r--r--src/amount.h10
-rw-r--r--src/bitcoin-cli.cpp32
-rw-r--r--src/bitcoin-tx.cpp4
-rw-r--r--src/chain.cpp7
-rw-r--r--src/chainparams.cpp1
-rw-r--r--src/checkpoints.cpp9
-rw-r--r--src/checkpoints.h3
-rw-r--r--src/clientversion.h2
-rw-r--r--src/compat/endian.h2
-rw-r--r--src/consensus/validation.h2
-rw-r--r--src/core_io.h2
-rw-r--r--src/core_read.cpp2
-rw-r--r--src/init.cpp36
-rw-r--r--src/json/LICENSE.txt24
-rw-r--r--src/json/json_spirit.h18
-rw-r--r--src/json/json_spirit_error_position.h54
-rw-r--r--src/json/json_spirit_reader.cpp137
-rw-r--r--src/json/json_spirit_reader.h62
-rw-r--r--src/json/json_spirit_reader_template.h612
-rw-r--r--src/json/json_spirit_stream_reader.h70
-rw-r--r--src/json/json_spirit_utils.h61
-rw-r--r--src/json/json_spirit_value.cpp8
-rw-r--r--src/json/json_spirit_value.h534
-rw-r--r--src/json/json_spirit_writer.cpp95
-rw-r--r--src/json/json_spirit_writer.h50
-rw-r--r--src/json/json_spirit_writer_template.h249
-rw-r--r--src/main.cpp115
-rw-r--r--src/main.h22
-rw-r--r--src/miner.cpp5
-rw-r--r--src/net.cpp25
-rw-r--r--src/net.h4
-rw-r--r--src/netbase.cpp6
-rw-r--r--src/qt/guiutil.cpp13
-rw-r--r--src/qt/guiutil.h10
-rw-r--r--src/qt/rpcconsole.cpp50
-rw-r--r--src/qt/rpcconsole.h6
-rw-r--r--src/qt/transactiondesc.cpp2
-rw-r--r--src/qt/transactionrecord.cpp2
-rw-r--r--src/rest.cpp126
-rw-r--r--src/rpcblockchain.cpp81
-rw-r--r--src/rpcclient.cpp33
-rw-r--r--src/rpcclient.h10
-rw-r--r--src/rpcmining.cpp79
-rw-r--r--src/rpcmisc.cpp47
-rw-r--r--src/rpcnet.cpp74
-rw-r--r--src/rpcprotocol.cpp28
-rw-r--r--src/rpcprotocol.h12
-rw-r--r--src/rpcrawtransaction.cpp122
-rw-r--r--src/rpcserver.cpp151
-rw-r--r--src/rpcserver.h231
-rw-r--r--src/test/Checkpoints_tests.cpp16
-rw-r--r--src/test/base58_tests.cpp58
-rw-r--r--src/test/miner_tests.cpp13
-rw-r--r--src/test/rpc_tests.cpp64
-rw-r--r--src/test/rpc_wallet_tests.cpp15
-rw-r--r--src/test/script_tests.cpp56
-rw-r--r--src/test/sighash_tests.cpp17
-rw-r--r--src/test/transaction_tests.cpp53
-rw-r--r--src/test/univalue_tests.cpp68
-rw-r--r--src/test/util_tests.cpp109
-rw-r--r--src/univalue/univalue.cpp107
-rw-r--r--src/univalue/univalue.h102
-rw-r--r--src/univalue/univalue_write.cpp9
-rw-r--r--src/util.cpp3
-rw-r--r--src/util.h2
-rw-r--r--src/utilmoneystr.cpp4
-rw-r--r--src/utilmoneystr.h2
-rw-r--r--src/utilstrencodings.cpp45
-rw-r--r--src/utilstrencodings.h18
-rw-r--r--src/validationinterface.cpp3
-rw-r--r--src/validationinterface.h3
-rw-r--r--src/wallet/rpcdump.cpp35
-rw-r--r--src/wallet/rpcwallet.cpp313
-rw-r--r--src/wallet/wallet.cpp24
-rw-r--r--src/wallet/wallet.h5
78 files changed, 1481 insertions, 3022 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1c2f770418..59618c4940 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -154,17 +154,6 @@ BITCOIN_CORE_H = \
wallet/wallet_ismine.h \
wallet/walletdb.h
-JSON_H = \
- json/json_spirit.h \
- json/json_spirit_error_position.h \
- json/json_spirit_reader.h \
- json/json_spirit_reader_template.h \
- json/json_spirit_stream_reader.h \
- json/json_spirit_utils.h \
- json/json_spirit_value.h \
- json/json_spirit_writer.h \
- json/json_spirit_writer_template.h
-
obj/build.h: FORCE
@$(MKDIR_P) $(builddir)/obj
@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
@@ -200,7 +189,6 @@ libbitcoin_server_a_SOURCES = \
txdb.cpp \
txmempool.cpp \
validationinterface.cpp \
- $(JSON_H) \
$(BITCOIN_CORE_H)
# wallet: shared between bitcoind and bitcoin-qt, but only linked
@@ -342,6 +330,7 @@ endif
bitcoin_cli_LDADD = \
$(LIBBITCOIN_CLI) \
+ $(LIBBITCOIN_UNIVALUE) \
$(LIBBITCOIN_UTIL) \
$(LIBSECP256K1)
diff --git a/src/alert.cpp b/src/alert.cpp
index aa7ac748da..ad81e74226 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -50,7 +50,7 @@ std::string CUnsignedAlert::ToString() const
BOOST_FOREACH(int n, setCancel)
strSetCancel += strprintf("%d ", n);
std::string strSetSubVer;
- BOOST_FOREACH(std::string str, setSubVer)
+ BOOST_FOREACH(const std::string& str, setSubVer)
strSetSubVer += "\"" + str + "\" ";
return strprintf(
"CAlert(\n"
@@ -110,7 +110,7 @@ bool CAlert::Cancels(const CAlert& alert) const
return (alert.nID <= nCancel || setCancel.count(alert.nID));
}
-bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
+bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const
{
// TODO: rework for client-version-embedded-in-strSubVer ?
return (IsInEffect() &&
diff --git a/src/alert.h b/src/alert.h
index 746967c4af..4f9fff9181 100644
--- a/src/alert.h
+++ b/src/alert.h
@@ -97,7 +97,7 @@ public:
uint256 GetHash() const;
bool IsInEffect() const;
bool Cancels(const CAlert& alert) const;
- bool AppliesTo(int nVersion, std::string strSubVerIn) const;
+ bool AppliesTo(int nVersion, const std::string& strSubVerIn) const;
bool AppliesToMe() const;
bool RelayTo(CNode* pnode) const;
bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
diff --git a/src/amount.h b/src/amount.h
index 9212244a88..7dc62edac4 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -16,7 +16,15 @@ typedef int64_t CAmount;
static const CAmount COIN = 100000000;
static const CAmount CENT = 1000000;
-/** No amount larger than this (in satoshi) is valid */
+/** No amount larger than this (in satoshi) is valid.
+ *
+ * Note that this constant is *not* the total money supply, which in Bitcoin
+ * currently happens to be less than 21,000,000 BTC for various reasons, but
+ * rather a sanity check. As this sanity check is used by consensus-critical
+ * validation code, the exact value of the MAX_MONEY constant is consensus
+ * critical; in unusual circumstances like a(nother) overflow bug that allowed
+ * for the creation of coins out of thin air modification could lead to a fork.
+ * */
static const CAmount MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 1269d7a119..d451720141 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -12,8 +12,9 @@
#include <boost/filesystem/operations.hpp>
+#include "univalue/univalue.h"
+
using namespace std;
-using namespace json_spirit;
std::string HelpMessageCli()
{
@@ -94,7 +95,7 @@ static bool AppInitRPC(int argc, char* argv[])
return true;
}
-Object CallRPC(const string& strMethod, const Array& params)
+UniValue CallRPC(const string& strMethod, const UniValue& params)
{
if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
throw runtime_error(strprintf(
@@ -142,10 +143,10 @@ Object CallRPC(const string& strMethod, const Array& params)
throw runtime_error("no response from server");
// Parse reply
- Value valReply;
- if (!read_string(strReply, valReply))
+ UniValue valReply(UniValue::VSTR);
+ if (!valReply.read(strReply))
throw runtime_error("couldn't parse reply from server");
- const Object& reply = valReply.get_obj();
+ const UniValue& reply = valReply.get_obj();
if (reply.empty())
throw runtime_error("expected reply to have result, error and id properties");
@@ -170,35 +171,34 @@ int CommandLineRPC(int argc, char *argv[])
// Parameters default to strings
std::vector<std::string> strParams(&argv[2], &argv[argc]);
- Array params = RPCConvertValues(strMethod, strParams);
+ UniValue params = RPCConvertValues(strMethod, strParams);
// Execute and handle connection failures with -rpcwait
const bool fWait = GetBoolArg("-rpcwait", false);
do {
try {
- const Object reply = CallRPC(strMethod, params);
+ const UniValue reply = CallRPC(strMethod, params);
// Parse reply
- const Value& result = find_value(reply, "result");
- const Value& error = find_value(reply, "error");
+ const UniValue& result = find_value(reply, "result");
+ const UniValue& error = find_value(reply, "error");
- if (error.type() != null_type) {
+ if (!error.isNull()) {
// Error
- const int code = find_value(error.get_obj(), "code").get_int();
+ int code = error["code"].get_int();
if (fWait && code == RPC_IN_WARMUP)
throw CConnectionFailed("server in warmup");
- strPrint = "error: " + write_string(error, false);
+ strPrint = "error: " + error.write();
nRet = abs(code);
} else {
// Result
- if (result.type() == null_type)
+ if (result.isNull())
strPrint = "";
- else if (result.type() == str_type)
+ else if (result.isStr())
strPrint = result.get_str();
else
- strPrint = write_string(result, true);
+ strPrint = result.write(2);
}
-
// Connection succeeded, no need to retry.
break;
}
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index c82d4f93a8..45990f6bd8 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -346,7 +346,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
UniValue keysObj = registers["privatekeys"];
fGivenKeys = true;
- for (unsigned int kidx = 0; kidx < keysObj.count(); kidx++) {
+ for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
if (!keysObj[kidx].isStr())
throw runtime_error("privatekey not a string");
CBitcoinSecret vchSecret;
@@ -363,7 +363,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
throw runtime_error("prevtxs register variable must be set.");
UniValue prevtxsObj = registers["prevtxs"];
{
- for (unsigned int previdx = 0; previdx < prevtxsObj.count(); previdx++) {
+ for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) {
UniValue prevOut = prevtxsObj[previdx];
if (!prevOut.isObject())
throw runtime_error("expected prevtxs internal object");
diff --git a/src/chain.cpp b/src/chain.cpp
index 719256106e..5b8ce076c4 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -82,9 +82,10 @@ CBlockIndex* CBlockIndex::GetAncestor(int height)
while (heightWalk > height) {
int heightSkip = GetSkipHeight(heightWalk);
int heightSkipPrev = GetSkipHeight(heightWalk - 1);
- if (heightSkip == height ||
- (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
- heightSkipPrev >= height))) {
+ if (pindexWalk->pskip != NULL &&
+ (heightSkip == height ||
+ (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
+ heightSkipPrev >= height)))) {
// Only follow pskip if pprev->pskip isn't better than pskip->pprev.
pindexWalk = pindexWalk->pskip;
heightWalk = heightSkip;
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 5f400b265c..7785417518 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -66,6 +66,7 @@ public:
*/
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
CMutableTransaction txNew;
+ txNew.nVersion = 1;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 2024486139..87f4ad7f2e 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -24,15 +24,6 @@ namespace Checkpoints {
*/
static const double SIGCHECK_VERIFICATION_FACTOR = 5.0;
- bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash)
- {
- const MapCheckpoints& checkpoints = data.mapCheckpoints;
-
- MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
- if (i == checkpoints.end()) return true;
- return hash == i->second;
- }
-
//! Guess how far we are in the verification process at the given block index
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) {
if (pindex==NULL)
diff --git a/src/checkpoints.h b/src/checkpoints.h
index a720f096c0..001e3cc801 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -26,9 +26,6 @@ struct CCheckpointData {
double fTransactionsPerDay;
};
-//! Returns true if block passes checkpoint checks
-bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash);
-
//! Return conservative estimate of total number of blocks, 0 if unknown
int GetTotalBlocksEstimate(const CCheckpointData& data);
diff --git a/src/clientversion.h b/src/clientversion.h
index 3c8c969f9d..5a06b310a3 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -15,7 +15,7 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 0
-#define CLIENT_VERSION_MINOR 10
+#define CLIENT_VERSION_MINOR 11
#define CLIENT_VERSION_REVISION 99
#define CLIENT_VERSION_BUILD 0
diff --git a/src/compat/endian.h b/src/compat/endian.h
index 4d041d6554..9fec2a07fa 100644
--- a/src/compat/endian.h
+++ b/src/compat/endian.h
@@ -15,6 +15,8 @@
#if defined(HAVE_ENDIAN_H)
#include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H)
+#include <sys/endian.h>
#endif
#if defined(WORDS_BIGENDIAN)
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index c92bec4fae..a97d983a31 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -48,7 +48,7 @@ public:
unsigned char _chRejectCode=0, std::string _strRejectReason="") {
return DoS(0, ret, _chRejectCode, _strRejectReason);
}
- bool Error(std::string strRejectReasonIn="") {
+ bool Error(const std::string& strRejectReasonIn) {
if (mode == MODE_VALID)
strRejectReason = strRejectReasonIn;
mode = MODE_ERROR;
diff --git a/src/core_io.h b/src/core_io.h
index 0989cf7437..115e3199dc 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -15,7 +15,7 @@ class uint256;
class UniValue;
// core_read.cpp
-extern CScript ParseScript(std::string s);
+extern CScript ParseScript(const std::string& s);
extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
extern uint256 ParseHashUV(const UniValue& v, const std::string& strName);
diff --git a/src/core_read.cpp b/src/core_read.cpp
index e064955ff0..f762f2c3b7 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -22,7 +22,7 @@
using namespace std;
-CScript ParseScript(std::string s)
+CScript ParseScript(const std::string& s)
{
CScript result;
diff --git a/src/init.cpp b/src/init.cpp
index 24e7e1c04a..e269019db9 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -318,7 +318,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT));
#ifdef USE_UPNP
#if USE_UPNP
- strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening)"));
+ strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening and no -proxy)"));
#else
strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0));
#endif
@@ -326,7 +326,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6"));
strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") +
" " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway"));
-
#ifdef ENABLE_WALLET
strUsage += HelpMessageGroup(_("Wallet options:"));
@@ -349,13 +348,12 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
-
#endif
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
if (GetBoolArg("-help-debug", false))
{
- strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1));
+ strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Disable expensive verification for known chain history (default: %u)"), 1));
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100));
strUsage += HelpMessageOpt("-disablesafemode", strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0));
strUsage += HelpMessageOpt("-testsafemode", strprintf(_("Force safe mode (default: %u)"), 0));
@@ -368,7 +366,7 @@ std::string HelpMessage(HelpMessageMode mode)
if (mode == HMM_BITCOIN_QT)
debugCategories += ", qt";
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
- _("If <category> is not supplied, output all debugging information.") + _("<category> can be:") + " " + debugCategories + ".");
+ _("If <category> is not supplied or if <category> = 1, output all debugging information.") + _("<category> can be:") + " " + debugCategories + ".");
#ifdef ENABLE_WALLET
strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0));
strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1));
@@ -403,6 +401,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), 0));
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
+ if (GetBoolArg("-help-debug", false))
+ strUsage += HelpMessageOpt("-blockversion=<n>", strprintf(_("Override block version to test forking scenarios (default: %d)"), (int)CBlock::CURRENT_VERSION));
strUsage += HelpMessageGroup(_("RPC server options:"));
strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands"));
@@ -535,7 +535,7 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
}
// -loadblock=
- BOOST_FOREACH(boost::filesystem::path &path, vImportFiles) {
+ BOOST_FOREACH(const boost::filesystem::path& path, vImportFiles) {
FILE *file = fopen(path.string().c_str(), "rb");
if (file) {
CImportingNow imp;
@@ -783,12 +783,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (nConnectTimeout <= 0)
nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
- // Continue to put "/P2SH/" in the coinbase to monitor
- // BIP16 support.
- // This can be removed eventually...
- const char* pszP2SH = "/P2SH/";
- COINBASE_FLAGS << std::vector<unsigned char>(pszP2SH, pszP2SH+strlen(pszP2SH));
-
// Fee-per-kilobyte amount considered the same as "free"
// If you are mining, be careful setting this:
// if you set it to zero then
@@ -931,15 +925,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
std::string warningString;
std::string errorString;
-
+
if (!CWallet::Verify(strWalletFile, warningString, errorString))
return false;
-
+
if (!warningString.empty())
InitWarning(warningString);
if (!errorString.empty())
return InitError(warningString);
-
+
} // (!fDisableWallet)
#endif // ENABLE_WALLET
// ********************************************************* Step 6: network initialization
@@ -948,7 +942,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (mapArgs.count("-onlynet")) {
std::set<enum Network> nets;
- BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) {
+ BOOST_FOREACH(const std::string& snet, mapMultiArgs["-onlynet"]) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
@@ -1005,13 +999,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
bool fBound = false;
if (fListen) {
if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
- BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
+ BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-bind"]) {
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind));
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
}
- BOOST_FOREACH(std::string strBind, mapMultiArgs["-whitebind"]) {
+ BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-whitebind"]) {
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, 0, false))
return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind));
@@ -1031,7 +1025,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
if (mapArgs.count("-externalip")) {
- BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) {
+ BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) {
CService addrLocal(strAddr, GetListenPort(), fNameLookup);
if (!addrLocal.IsValid())
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr));
@@ -1039,7 +1033,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
}
- BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"])
+ BOOST_FOREACH(const std::string& strDest, mapMultiArgs["-seednode"])
AddOneShot(strDest);
// ********************************************************* Step 7: load block chain
@@ -1377,7 +1371,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
std::vector<boost::filesystem::path> vImportFiles;
if (mapArgs.count("-loadblock"))
{
- BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"])
+ BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"])
vImportFiles.push_back(strFile);
}
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
diff --git a/src/json/LICENSE.txt b/src/json/LICENSE.txt
deleted file mode 100644
index 797d5363b3..0000000000
--- a/src/json/LICENSE.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-The MIT License
-
-Copyright (c) 2007 - 2009 John W. Wilkinson
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/json/json_spirit.h b/src/json/json_spirit.h
deleted file mode 100644
index ac1879d5b3..0000000000
--- a/src/json/json_spirit.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef JSON_SPIRIT
-#define JSON_SPIRIT
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include "json_spirit_value.h"
-#include "json_spirit_reader.h"
-#include "json_spirit_writer.h"
-#include "json_spirit_utils.h"
-
-#endif
diff --git a/src/json/json_spirit_error_position.h b/src/json/json_spirit_error_position.h
deleted file mode 100644
index 17208507df..0000000000
--- a/src/json/json_spirit_error_position.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef JSON_SPIRIT_ERROR_POSITION
-#define JSON_SPIRIT_ERROR_POSITION
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include <string>
-
-namespace json_spirit
-{
- // An Error_position exception is thrown by the "read_or_throw" functions below on finding an error.
- // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read"
- // functions that return a bool.
- //
- struct Error_position
- {
- Error_position();
- Error_position( unsigned int line, unsigned int column, const std::string& reason );
- bool operator==( const Error_position& lhs ) const;
- unsigned int line_;
- unsigned int column_;
- std::string reason_;
- };
-
- inline Error_position::Error_position()
- : line_( 0 )
- , column_( 0 )
- {
- }
-
- inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason )
- : line_( line )
- , column_( column )
- , reason_( reason )
- {
- }
-
- inline bool Error_position::operator==( const Error_position& lhs ) const
- {
- if( this == &lhs ) return true;
-
- return ( reason_ == lhs.reason_ ) &&
- ( line_ == lhs.line_ ) &&
- ( column_ == lhs.column_ );
-}
-}
-
-#endif
diff --git a/src/json/json_spirit_reader.cpp b/src/json/json_spirit_reader.cpp
deleted file mode 100644
index aa4f637226..0000000000
--- a/src/json/json_spirit_reader.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#include "json_spirit_reader.h"
-#include "json_spirit_reader_template.h"
-
-using namespace json_spirit;
-
-bool json_spirit::read( const std::string& s, Value& value )
-{
- return read_string( s, value );
-}
-
-void json_spirit::read_or_throw( const std::string& s, Value& value )
-{
- read_string_or_throw( s, value );
-}
-
-bool json_spirit::read( std::istream& is, Value& value )
-{
- return read_stream( is, value );
-}
-
-void json_spirit::read_or_throw( std::istream& is, Value& value )
-{
- read_stream_or_throw( is, value );
-}
-
-bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value )
-{
- return read_range( begin, end, value );
-}
-
-void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value )
-{
- begin = read_range_or_throw( begin, end, value );
-}
-
-#ifndef BOOST_NO_STD_WSTRING
-
-bool json_spirit::read( const std::wstring& s, wValue& value )
-{
- return read_string( s, value );
-}
-
-void json_spirit::read_or_throw( const std::wstring& s, wValue& value )
-{
- read_string_or_throw( s, value );
-}
-
-bool json_spirit::read( std::wistream& is, wValue& value )
-{
- return read_stream( is, value );
-}
-
-void json_spirit::read_or_throw( std::wistream& is, wValue& value )
-{
- read_stream_or_throw( is, value );
-}
-
-bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value )
-{
- return read_range( begin, end, value );
-}
-
-void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value )
-{
- begin = read_range_or_throw( begin, end, value );
-}
-
-#endif
-
-bool json_spirit::read( const std::string& s, mValue& value )
-{
- return read_string( s, value );
-}
-
-void json_spirit::read_or_throw( const std::string& s, mValue& value )
-{
- read_string_or_throw( s, value );
-}
-
-bool json_spirit::read( std::istream& is, mValue& value )
-{
- return read_stream( is, value );
-}
-
-void json_spirit::read_or_throw( std::istream& is, mValue& value )
-{
- read_stream_or_throw( is, value );
-}
-
-bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value )
-{
- return read_range( begin, end, value );
-}
-
-void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value )
-{
- begin = read_range_or_throw( begin, end, value );
-}
-
-#ifndef BOOST_NO_STD_WSTRING
-
-bool json_spirit::read( const std::wstring& s, wmValue& value )
-{
- return read_string( s, value );
-}
-
-void json_spirit::read_or_throw( const std::wstring& s, wmValue& value )
-{
- read_string_or_throw( s, value );
-}
-
-bool json_spirit::read( std::wistream& is, wmValue& value )
-{
- return read_stream( is, value );
-}
-
-void json_spirit::read_or_throw( std::wistream& is, wmValue& value )
-{
- read_stream_or_throw( is, value );
-}
-
-bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value )
-{
- return read_range( begin, end, value );
-}
-
-void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value )
-{
- begin = read_range_or_throw( begin, end, value );
-}
-
-#endif
diff --git a/src/json/json_spirit_reader.h b/src/json/json_spirit_reader.h
deleted file mode 100644
index 96494a9789..0000000000
--- a/src/json/json_spirit_reader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef JSON_SPIRIT_READER
-#define JSON_SPIRIT_READER
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include "json_spirit_value.h"
-#include "json_spirit_error_position.h"
-#include <iostream>
-
-namespace json_spirit
-{
- // functions to reads a JSON values
-
- bool read( const std::string& s, Value& value );
- bool read( std::istream& is, Value& value );
- bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );
-
- void read_or_throw( const std::string& s, Value& value );
- void read_or_throw( std::istream& is, Value& value );
- void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );
-
-#ifndef BOOST_NO_STD_WSTRING
-
- bool read( const std::wstring& s, wValue& value );
- bool read( std::wistream& is, wValue& value );
- bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );
-
- void read_or_throw( const std::wstring& s, wValue& value );
- void read_or_throw( std::wistream& is, wValue& value );
- void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );
-
-#endif
-
- bool read( const std::string& s, mValue& value );
- bool read( std::istream& is, mValue& value );
- bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );
-
- void read_or_throw( const std::string& s, mValue& value );
- void read_or_throw( std::istream& is, mValue& value );
- void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );
-
-#ifndef BOOST_NO_STD_WSTRING
-
- bool read( const std::wstring& s, wmValue& value );
- bool read( std::wistream& is, wmValue& value );
- bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );
-
- void read_or_throw( const std::wstring& s, wmValue& value );
- void read_or_throw( std::wistream& is, wmValue& value );
- void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );
-
-#endif
-}
-
-#endif
diff --git a/src/json/json_spirit_reader_template.h b/src/json/json_spirit_reader_template.h
deleted file mode 100644
index 46f5892f62..0000000000
--- a/src/json/json_spirit_reader_template.h
+++ /dev/null
@@ -1,612 +0,0 @@
-#ifndef JSON_SPIRIT_READER_TEMPLATE
-#define JSON_SPIRIT_READER_TEMPLATE
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#include "json_spirit_value.h"
-#include "json_spirit_error_position.h"
-
-//#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread
-
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include <boost/version.hpp>
-
-#if BOOST_VERSION >= 103800
- #include <boost/spirit/include/classic_core.hpp>
- #include <boost/spirit/include/classic_confix.hpp>
- #include <boost/spirit/include/classic_escape_char.hpp>
- #include <boost/spirit/include/classic_multi_pass.hpp>
- #include <boost/spirit/include/classic_position_iterator.hpp>
- #define spirit_namespace boost::spirit::classic
-#else
- #include <boost/spirit/core.hpp>
- #include <boost/spirit/utility/confix.hpp>
- #include <boost/spirit/utility/escape_char.hpp>
- #include <boost/spirit/iterator/multi_pass.hpp>
- #include <boost/spirit/iterator/position_iterator.hpp>
- #define spirit_namespace boost::spirit
-#endif
-
-namespace json_spirit
-{
- const spirit_namespace::int_parser < int64_t > int64_p = spirit_namespace::int_parser < int64_t >();
- const spirit_namespace::uint_parser< uint64_t > uint64_p = spirit_namespace::uint_parser< uint64_t >();
-
- template< class Iter_type >
- bool is_eq( Iter_type first, Iter_type last, const char* c_str )
- {
- for( Iter_type i = first; i != last; ++i, ++c_str )
- {
- if( *c_str == 0 ) return false;
-
- if( *i != *c_str ) return false;
- }
-
- return true;
- }
-
- template< class Char_type >
- Char_type hex_to_num( const Char_type c )
- {
- if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0';
- if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10;
- if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10;
- return 0;
- }
-
- template< class Char_type, class Iter_type >
- Char_type hex_str_to_char( Iter_type& begin )
- {
- const Char_type c1( *( ++begin ) );
- const Char_type c2( *( ++begin ) );
-
- return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 );
- }
-
- template< class Char_type, class Iter_type >
- Char_type unicode_str_to_char( Iter_type& begin )
- {
- const Char_type c1( *( ++begin ) );
- const Char_type c2( *( ++begin ) );
- const Char_type c3( *( ++begin ) );
- const Char_type c4( *( ++begin ) );
-
- return ( hex_to_num( c1 ) << 12 ) +
- ( hex_to_num( c2 ) << 8 ) +
- ( hex_to_num( c3 ) << 4 ) +
- hex_to_num( c4 );
- }
-
- template< class String_type >
- void append_esc_char_and_incr_iter( String_type& s,
- typename String_type::const_iterator& begin,
- typename String_type::const_iterator end )
- {
- typedef typename String_type::value_type Char_type;
-
- const Char_type c2( *begin );
-
- switch( c2 )
- {
- case 't': s += '\t'; break;
- case 'b': s += '\b'; break;
- case 'f': s += '\f'; break;
- case 'n': s += '\n'; break;
- case 'r': s += '\r'; break;
- case '\\': s += '\\'; break;
- case '/': s += '/'; break;
- case '"': s += '"'; break;
- case 'x':
- {
- if( end - begin >= 3 ) // expecting "xHH..."
- {
- s += hex_str_to_char< Char_type >( begin );
- }
- break;
- }
- case 'u':
- {
- if( end - begin >= 5 ) // expecting "uHHHH..."
- {
- s += unicode_str_to_char< Char_type >( begin );
- }
- break;
- }
- }
- }
-
- template< class String_type >
- String_type substitute_esc_chars( typename String_type::const_iterator begin,
- typename String_type::const_iterator end )
- {
- typedef typename String_type::const_iterator Iter_type;
-
- if( end - begin < 2 ) return String_type( begin, end );
-
- String_type result;
-
- result.reserve( end - begin );
-
- const Iter_type end_minus_1( end - 1 );
-
- Iter_type substr_start = begin;
- Iter_type i = begin;
-
- for( ; i < end_minus_1; ++i )
- {
- if( *i == '\\' )
- {
- result.append( substr_start, i );
-
- ++i; // skip the '\'
-
- append_esc_char_and_incr_iter( result, i, end );
-
- substr_start = i + 1;
- }
- }
-
- result.append( substr_start, end );
-
- return result;
- }
-
- template< class String_type >
- String_type get_str_( typename String_type::const_iterator begin,
- typename String_type::const_iterator end )
- {
- assert( end - begin >= 2 );
-
- typedef typename String_type::const_iterator Iter_type;
-
- Iter_type str_without_quotes( ++begin );
- Iter_type end_without_quotes( --end );
-
- return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes );
- }
-
- inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end )
- {
- return get_str_< std::string >( begin, end );
- }
-
- inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end )
- {
- return get_str_< std::wstring >( begin, end );
- }
-
- template< class String_type, class Iter_type >
- String_type get_str( Iter_type begin, Iter_type end )
- {
- const String_type tmp( begin, end ); // convert multipass iterators to string iterators
-
- return get_str( tmp.begin(), tmp.end() );
- }
-
- // this class's methods get called by the spirit parse resulting
- // in the creation of a JSON object or array
- //
- // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator
- //
- template< class Value_type, class Iter_type >
- class Semantic_actions
- {
- public:
-
- typedef typename Value_type::Config_type Config_type;
- typedef typename Config_type::String_type String_type;
- typedef typename Config_type::Object_type Object_type;
- typedef typename Config_type::Array_type Array_type;
- typedef typename String_type::value_type Char_type;
-
- Semantic_actions( Value_type& value )
- : value_( value )
- , current_p_( 0 )
- {
- }
-
- void begin_obj( Char_type c )
- {
- assert( c == '{' );
-
- begin_compound< Object_type >();
- }
-
- void end_obj( Char_type c )
- {
- assert( c == '}' );
-
- end_compound();
- }
-
- void begin_array( Char_type c )
- {
- assert( c == '[' );
-
- begin_compound< Array_type >();
- }
-
- void end_array( Char_type c )
- {
- assert( c == ']' );
-
- end_compound();
- }
-
- void new_name( Iter_type begin, Iter_type end )
- {
- assert( current_p_->type() == obj_type );
-
- name_ = get_str< String_type >( begin, end );
- }
-
- void new_str( Iter_type begin, Iter_type end )
- {
- add_to_current( get_str< String_type >( begin, end ) );
- }
-
- void new_true( Iter_type begin, Iter_type end )
- {
- assert( is_eq( begin, end, "true" ) );
-
- add_to_current( true );
- }
-
- void new_false( Iter_type begin, Iter_type end )
- {
- assert( is_eq( begin, end, "false" ) );
-
- add_to_current( false );
- }
-
- void new_null( Iter_type begin, Iter_type end )
- {
- assert( is_eq( begin, end, "null" ) );
-
- add_to_current( Value_type() );
- }
-
- void new_int( int64_t i )
- {
- add_to_current( i );
- }
-
- void new_uint64( uint64_t ui )
- {
- add_to_current( ui );
- }
-
- void new_real( double d )
- {
- add_to_current( d );
- }
-
- private:
-
- Semantic_actions& operator=( const Semantic_actions& );
- // to prevent "assignment operator could not be generated" warning
-
- Value_type* add_first( const Value_type& value )
- {
- assert( current_p_ == 0 );
-
- value_ = value;
- current_p_ = &value_;
- return current_p_;
- }
-
- template< class Array_or_obj >
- void begin_compound()
- {
- if( current_p_ == 0 )
- {
- add_first( Array_or_obj() );
- }
- else
- {
- stack_.push_back( current_p_ );
-
- Array_or_obj new_array_or_obj; // avoid copy by building new array or object in place
-
- current_p_ = add_to_current( new_array_or_obj );
- }
- }
-
- void end_compound()
- {
- if( current_p_ != &value_ )
- {
- current_p_ = stack_.back();
-
- stack_.pop_back();
- }
- }
-
- Value_type* add_to_current( const Value_type& value )
- {
- if( current_p_ == 0 )
- {
- return add_first( value );
- }
- else if( current_p_->type() == array_type )
- {
- current_p_->get_array().push_back( value );
-
- return &current_p_->get_array().back();
- }
-
- assert( current_p_->type() == obj_type );
-
- return &Config_type::add( current_p_->get_obj(), name_, value );
- }
-
- Value_type& value_; // this is the object or array that is being created
- Value_type* current_p_; // the child object or array that is currently being constructed
-
- std::vector< Value_type* > stack_; // previous child objects and arrays
-
- String_type name_; // of current name/value pair
- };
-
- template< typename Iter_type >
- void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason )
- {
- throw Error_position( i.get_position().line, i.get_position().column, reason );
- }
-
- template< typename Iter_type >
- void throw_error( Iter_type i, const std::string& reason )
- {
- throw reason;
- }
-
- // the spirit grammer
- //
- template< class Value_type, class Iter_type >
- class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > >
- {
- public:
-
- typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t;
-
- Json_grammer( Semantic_actions_t& semantic_actions )
- : actions_( semantic_actions )
- {
- }
-
- static void throw_not_value( Iter_type begin, Iter_type end )
- {
- throw_error( begin, "not a value" );
- }
-
- static void throw_not_array( Iter_type begin, Iter_type end )
- {
- throw_error( begin, "not an array" );
- }
-
- static void throw_not_object( Iter_type begin, Iter_type end )
- {
- throw_error( begin, "not an object" );
- }
-
- static void throw_not_pair( Iter_type begin, Iter_type end )
- {
- throw_error( begin, "not a pair" );
- }
-
- static void throw_not_colon( Iter_type begin, Iter_type end )
- {
- throw_error( begin, "no colon in pair" );
- }
-
- static void throw_not_string( Iter_type begin, Iter_type end )
- {
- throw_error( begin, "not a string" );
- }
-
- template< typename ScannerT >
- class definition
- {
- public:
-
- definition( const Json_grammer& self )
- {
- using namespace spirit_namespace;
-
- typedef typename Value_type::String_type::value_type Char_type;
-
- // first we convert the semantic action class methods to functors with the
- // parameter signature expected by spirit
-
- typedef boost::function< void( Char_type ) > Char_action;
- typedef boost::function< void( Iter_type, Iter_type ) > Str_action;
- typedef boost::function< void( double ) > Real_action;
- typedef boost::function< void( int64_t ) > Int_action;
- typedef boost::function< void( uint64_t ) > Uint64_action;
-
- Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) );
- Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) );
- Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) );
- Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) );
- Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) );
- Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) );
- Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) );
- Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) );
- Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) );
- Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) );
- Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) );
- Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) );
-
- // actual grammer
-
- json_
- = value_ | eps_p[ &throw_not_value ]
- ;
-
- value_
- = string_[ new_str ]
- | number_
- | object_
- | array_
- | str_p( "true" ) [ new_true ]
- | str_p( "false" )[ new_false ]
- | str_p( "null" ) [ new_null ]
- ;
-
- object_
- = ch_p('{')[ begin_obj ]
- >> !members_
- >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] )
- ;
-
- members_
- = pair_ >> *( ',' >> pair_ )
- ;
-
- pair_
- = string_[ new_name ]
- >> ( ':' | eps_p[ &throw_not_colon ] )
- >> ( value_ | eps_p[ &throw_not_value ] )
- ;
-
- array_
- = ch_p('[')[ begin_array ]
- >> !elements_
- >> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] )
- ;
-
- elements_
- = value_ >> *( ',' >> value_ )
- ;
-
- string_
- = lexeme_d // this causes white space inside a string to be retained
- [
- confix_p
- (
- '"',
- *lex_escape_ch_p,
- '"'
- )
- ]
- ;
-
- number_
- = strict_real_p[ new_real ]
- | int64_p [ new_int ]
- | uint64_p [ new_uint64 ]
- ;
- }
-
- spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, string_, number_;
-
- const spirit_namespace::rule< ScannerT >& start() const { return json_; }
- };
-
- private:
-
- Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning
-
- Semantic_actions_t& actions_;
- };
-
- template< class Iter_type, class Value_type >
- Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )
- {
- Semantic_actions< Value_type, Iter_type > semantic_actions( value );
-
- const spirit_namespace::parse_info< Iter_type > info =
- spirit_namespace::parse( begin, end,
- Json_grammer< Value_type, Iter_type >( semantic_actions ),
- spirit_namespace::space_p );
-
- if( !info.hit )
- {
- assert( false ); // in theory exception should already have been thrown
- throw_error( info.stop, "error" );
- }
-
- return info.stop;
- }
-
- template< class Iter_type, class Value_type >
- void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )
- {
- typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t;
-
- const Posn_iter_t posn_begin( begin, end );
- const Posn_iter_t posn_end( end, end );
-
- read_range_or_throw( posn_begin, posn_end, value );
- }
-
- template< class Iter_type, class Value_type >
- bool read_range( Iter_type& begin, Iter_type end, Value_type& value )
- {
- try
- {
- begin = read_range_or_throw( begin, end, value );
-
- return true;
- }
- catch( ... )
- {
- return false;
- }
- }
-
- template< class String_type, class Value_type >
- void read_string_or_throw( const String_type& s, Value_type& value )
- {
- add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value );
- }
-
- template< class String_type, class Value_type >
- bool read_string( const String_type& s, Value_type& value )
- {
- typename String_type::const_iterator begin = s.begin();
-
- return read_range( begin, s.end(), value );
- }
-
- template< class Istream_type >
- struct Multi_pass_iters
- {
- typedef typename Istream_type::char_type Char_type;
- typedef std::istream_iterator< Char_type, Char_type > istream_iter;
- typedef spirit_namespace::multi_pass< istream_iter > Mp_iter;
-
- Multi_pass_iters( Istream_type& is )
- {
- is.unsetf( std::ios::skipws );
-
- begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) );
- end_ = spirit_namespace::make_multi_pass( istream_iter() );
- }
-
- Mp_iter begin_;
- Mp_iter end_;
- };
-
- template< class Istream_type, class Value_type >
- bool read_stream( Istream_type& is, Value_type& value )
- {
- Multi_pass_iters< Istream_type > mp_iters( is );
-
- return read_range( mp_iters.begin_, mp_iters.end_, value );
- }
-
- template< class Istream_type, class Value_type >
- void read_stream_or_throw( Istream_type& is, Value_type& value )
- {
- const Multi_pass_iters< Istream_type > mp_iters( is );
-
- add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value );
- }
-}
-
-#endif
diff --git a/src/json/json_spirit_stream_reader.h b/src/json/json_spirit_stream_reader.h
deleted file mode 100644
index 7e59c9adc2..0000000000
--- a/src/json/json_spirit_stream_reader.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef JSON_SPIRIT_READ_STREAM
-#define JSON_SPIRIT_READ_STREAM
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include "json_spirit_reader_template.h"
-
-namespace json_spirit
-{
- // these classes allows you to read multiple top level contiguous values from a stream,
- // the normal stream read functions have a bug that prevent multiple top level values
- // from being read unless they are separated by spaces
-
- template< class Istream_type, class Value_type >
- class Stream_reader
- {
- public:
-
- Stream_reader( Istream_type& is )
- : iters_( is )
- {
- }
-
- bool read_next( Value_type& value )
- {
- return read_range( iters_.begin_, iters_.end_, value );
- }
-
- private:
-
- typedef Multi_pass_iters< Istream_type > Mp_iters;
-
- Mp_iters iters_;
- };
-
- template< class Istream_type, class Value_type >
- class Stream_reader_thrower
- {
- public:
-
- Stream_reader_thrower( Istream_type& is )
- : iters_( is )
- , posn_begin_( iters_.begin_, iters_.end_ )
- , posn_end_( iters_.end_, iters_.end_ )
- {
- }
-
- void read_next( Value_type& value )
- {
- posn_begin_ = read_range_or_throw( posn_begin_, posn_end_, value );
- }
-
- private:
-
- typedef Multi_pass_iters< Istream_type > Mp_iters;
- typedef spirit_namespace::position_iterator< typename Mp_iters::Mp_iter > Posn_iter_t;
-
- Mp_iters iters_;
- Posn_iter_t posn_begin_, posn_end_;
- };
-}
-
-#endif
diff --git a/src/json/json_spirit_utils.h b/src/json/json_spirit_utils.h
deleted file mode 100644
index 553e3b96a4..0000000000
--- a/src/json/json_spirit_utils.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef JSON_SPIRIT_UTILS
-#define JSON_SPIRIT_UTILS
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include "json_spirit_value.h"
-#include <map>
-
-namespace json_spirit
-{
- template< class Obj_t, class Map_t >
- void obj_to_map( const Obj_t& obj, Map_t& mp_obj )
- {
- mp_obj.clear();
-
- for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i )
- {
- mp_obj[ i->name_ ] = i->value_;
- }
- }
-
- template< class Obj_t, class Map_t >
- void map_to_obj( const Map_t& mp_obj, Obj_t& obj )
- {
- obj.clear();
-
- for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i )
- {
- obj.push_back( typename Obj_t::value_type( i->first, i->second ) );
- }
- }
-
- typedef std::map< std::string, Value > Mapped_obj;
-
-#ifndef BOOST_NO_STD_WSTRING
- typedef std::map< std::wstring, wValue > wMapped_obj;
-#endif
-
- template< class Object_type, class String_type >
- const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name )
- {
- for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i )
- {
- if( i->name_ == name )
- {
- return i->value_;
- }
- }
-
- return Object_type::value_type::Value_type::null;
- }
-}
-
-#endif
diff --git a/src/json/json_spirit_value.cpp b/src/json/json_spirit_value.cpp
deleted file mode 100644
index 44d2f06a01..0000000000
--- a/src/json/json_spirit_value.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-/* Copyright (c) 2007 John W Wilkinson
-
- This source code can be used for any purpose as long as
- this comment is retained. */
-
-// json spirit version 2.00
-
-#include "json_spirit_value.h"
diff --git a/src/json/json_spirit_value.h b/src/json/json_spirit_value.h
deleted file mode 100644
index 13cc89210c..0000000000
--- a/src/json/json_spirit_value.h
+++ /dev/null
@@ -1,534 +0,0 @@
-#ifndef JSON_SPIRIT_VALUE
-#define JSON_SPIRIT_VALUE
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include <vector>
-#include <map>
-#include <string>
-#include <cassert>
-#include <sstream>
-#include <stdexcept>
-#include <stdint.h>
-#include <boost/config.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/variant.hpp>
-
-namespace json_spirit
-{
- enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
- static const char* Value_type_name[]={"obj", "array", "str", "bool", "int", "real", "null"};
-
- template< class Config > // Config determines whether the value uses std::string or std::wstring and
- // whether JSON Objects are represented as vectors or maps
- class Value_impl
- {
- public:
-
- typedef Config Config_type;
- typedef typename Config::String_type String_type;
- typedef typename Config::Object_type Object;
- typedef typename Config::Array_type Array;
- typedef typename String_type::const_pointer Const_str_ptr; // eg const char*
-
- Value_impl(); // creates null value
- Value_impl( Const_str_ptr value );
- Value_impl( const String_type& value );
- Value_impl( const Object& value );
- Value_impl( const Array& value );
- Value_impl( bool value );
- Value_impl( int value );
- Value_impl( int64_t value );
- Value_impl( uint64_t value );
- Value_impl( double value );
-
- Value_impl( const Value_impl& other );
-
- bool operator==( const Value_impl& lhs ) const;
-
- Value_impl& operator=( const Value_impl& lhs );
-
- Value_type type() const;
-
- bool is_uint64() const;
- bool is_null() const;
-
- const String_type& get_str() const;
- const Object& get_obj() const;
- const Array& get_array() const;
- bool get_bool() const;
- int get_int() const;
- int64_t get_int64() const;
- uint64_t get_uint64() const;
- double get_real() const;
-
- Object& get_obj();
- Array& get_array();
-
- template< typename T > T get_value() const; // example usage: int i = value.get_value< int >();
- // or double d = value.get_value< double >();
-
- static const Value_impl null;
-
- private:
-
- void check_type( const Value_type vtype ) const;
-
- typedef boost::variant< String_type,
- boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >,
- bool, int64_t, double > Variant;
-
- Value_type type_;
- Variant v_;
- bool is_uint64_;
- };
-
- // vector objects
-
- template< class Config >
- struct Pair_impl
- {
- typedef typename Config::String_type String_type;
- typedef typename Config::Value_type Value_type;
-
- Pair_impl( const String_type& name, const Value_type& value );
-
- bool operator==( const Pair_impl& lhs ) const;
-
- String_type name_;
- Value_type value_;
- };
-
- template< class String >
- struct Config_vector
- {
- typedef String String_type;
- typedef Value_impl< Config_vector > Value_type;
- typedef Pair_impl < Config_vector > Pair_type;
- typedef std::vector< Value_type > Array_type;
- typedef std::vector< Pair_type > Object_type;
-
- static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
- {
- obj.push_back( Pair_type( name , value ) );
-
- return obj.back().value_;
- }
-
- static String_type get_name( const Pair_type& pair )
- {
- return pair.name_;
- }
-
- static Value_type get_value( const Pair_type& pair )
- {
- return pair.value_;
- }
- };
-
- // typedefs for ASCII
-
- typedef Config_vector< std::string > Config;
-
- typedef Config::Value_type Value;
- typedef Config::Pair_type Pair;
- typedef Config::Object_type Object;
- typedef Config::Array_type Array;
-
- // typedefs for Unicode
-
-#ifndef BOOST_NO_STD_WSTRING
-
- typedef Config_vector< std::wstring > wConfig;
-
- typedef wConfig::Value_type wValue;
- typedef wConfig::Pair_type wPair;
- typedef wConfig::Object_type wObject;
- typedef wConfig::Array_type wArray;
-#endif
-
- // map objects
-
- template< class String >
- struct Config_map
- {
- typedef String String_type;
- typedef Value_impl< Config_map > Value_type;
- typedef std::vector< Value_type > Array_type;
- typedef std::map< String_type, Value_type > Object_type;
- typedef typename Object_type::value_type Pair_type;
-
- static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
- {
- return obj[ name ] = value;
- }
-
- static String_type get_name( const Pair_type& pair )
- {
- return pair.first;
- }
-
- static Value_type get_value( const Pair_type& pair )
- {
- return pair.second;
- }
- };
-
- // typedefs for ASCII
-
- typedef Config_map< std::string > mConfig;
-
- typedef mConfig::Value_type mValue;
- typedef mConfig::Object_type mObject;
- typedef mConfig::Array_type mArray;
-
- // typedefs for Unicode
-
-#ifndef BOOST_NO_STD_WSTRING
-
- typedef Config_map< std::wstring > wmConfig;
-
- typedef wmConfig::Value_type wmValue;
- typedef wmConfig::Object_type wmObject;
- typedef wmConfig::Array_type wmArray;
-
-#endif
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
- //
- // implementation
-
- template< class Config >
- const Value_impl< Config > Value_impl< Config >::null;
-
- template< class Config >
- Value_impl< Config >::Value_impl()
- : type_( null_type )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( const Const_str_ptr value )
- : type_( str_type )
- , v_( String_type( value ) )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( const String_type& value )
- : type_( str_type )
- , v_( value )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( const Object& value )
- : type_( obj_type )
- , v_( value )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( const Array& value )
- : type_( array_type )
- , v_( value )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( bool value )
- : type_( bool_type )
- , v_( value )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( int value )
- : type_( int_type )
- , v_( static_cast< int64_t >( value ) )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( int64_t value )
- : type_( int_type )
- , v_( value )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( uint64_t value )
- : type_( int_type )
- , v_( static_cast< int64_t >( value ) )
- , is_uint64_( true )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( double value )
- : type_( real_type )
- , v_( value )
- , is_uint64_( false )
- {
- }
-
- template< class Config >
- Value_impl< Config >::Value_impl( const Value_impl< Config >& other )
- : type_( other.type() )
- , v_( other.v_ )
- , is_uint64_( other.is_uint64_ )
- {
- }
-
- template< class Config >
- Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs )
- {
- Value_impl tmp( lhs );
-
- std::swap( type_, tmp.type_ );
- std::swap( v_, tmp.v_ );
- std::swap( is_uint64_, tmp.is_uint64_ );
-
- return *this;
- }
-
- template< class Config >
- bool Value_impl< Config >::operator==( const Value_impl& lhs ) const
- {
- if( this == &lhs ) return true;
-
- if( type() != lhs.type() ) return false;
-
- return v_ == lhs.v_;
- }
-
- template< class Config >
- Value_type Value_impl< Config >::type() const
- {
- return type_;
- }
-
- template< class Config >
- bool Value_impl< Config >::is_uint64() const
- {
- return is_uint64_;
- }
-
- template< class Config >
- bool Value_impl< Config >::is_null() const
- {
- return type() == null_type;
- }
-
- template< class Config >
- void Value_impl< Config >::check_type( const Value_type vtype ) const
- {
- if( type() != vtype )
- {
- std::ostringstream os;
-
- ///// Bitcoin: Tell the types by name instead of by number
- os << "value is type " << Value_type_name[type()] << ", expected " << Value_type_name[vtype];
-
- throw std::runtime_error( os.str() );
- }
- }
-
- template< class Config >
- const typename Config::String_type& Value_impl< Config >::get_str() const
- {
- check_type( str_type );
-
- return *boost::get< String_type >( &v_ );
- }
-
- template< class Config >
- const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const
- {
- check_type( obj_type );
-
- return *boost::get< Object >( &v_ );
- }
-
- template< class Config >
- const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const
- {
- check_type( array_type );
-
- return *boost::get< Array >( &v_ );
- }
-
- template< class Config >
- bool Value_impl< Config >::get_bool() const
- {
- check_type( bool_type );
-
- return boost::get< bool >( v_ );
- }
-
- template< class Config >
- int Value_impl< Config >::get_int() const
- {
- check_type( int_type );
-
- return static_cast< int >( get_int64() );
- }
-
- template< class Config >
- int64_t Value_impl< Config >::get_int64() const
- {
- check_type( int_type );
-
- return boost::get< int64_t >( v_ );
- }
-
- template< class Config >
- uint64_t Value_impl< Config >::get_uint64() const
- {
- check_type( int_type );
-
- return static_cast< uint64_t >( get_int64() );
- }
-
- template< class Config >
- double Value_impl< Config >::get_real() const
- {
- if( type() == int_type )
- {
- return is_uint64() ? static_cast< double >( get_uint64() )
- : static_cast< double >( get_int64() );
- }
-
- check_type( real_type );
-
- return boost::get< double >( v_ );
- }
-
- template< class Config >
- typename Value_impl< Config >::Object& Value_impl< Config >::get_obj()
- {
- check_type( obj_type );
-
- return *boost::get< Object >( &v_ );
- }
-
- template< class Config >
- typename Value_impl< Config >::Array& Value_impl< Config >::get_array()
- {
- check_type( array_type );
-
- return *boost::get< Array >( &v_ );
- }
-
- template< class Config >
- Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value )
- : name_( name )
- , value_( value )
- {
- }
-
- template< class Config >
- bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const
- {
- if( this == &lhs ) return true;
-
- return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ );
- }
-
- // converts a C string, ie. 8 bit char array, to a string object
- //
- template < class String_type >
- String_type to_str( const char* c_str )
- {
- String_type result;
-
- for( const char* p = c_str; *p != 0; ++p )
- {
- result += *p;
- }
-
- return result;
- }
-
- //
-
- namespace internal_
- {
- template< typename T >
- struct Type_to_type
- {
- };
-
- template< class Value >
- int get_value( const Value& value, Type_to_type< int > )
- {
- return value.get_int();
- }
-
- template< class Value >
- int64_t get_value( const Value& value, Type_to_type< int64_t > )
- {
- return value.get_int64();
- }
-
- template< class Value >
- uint64_t get_value( const Value& value, Type_to_type< uint64_t > )
- {
- return value.get_uint64();
- }
-
- template< class Value >
- double get_value( const Value& value, Type_to_type< double > )
- {
- return value.get_real();
- }
-
- template< class Value >
- typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > )
- {
- return value.get_str();
- }
-
- template< class Value >
- typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > )
- {
- return value.get_array();
- }
-
- template< class Value >
- typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > )
- {
- return value.get_obj();
- }
-
- template< class Value >
- bool get_value( const Value& value, Type_to_type< bool > )
- {
- return value.get_bool();
- }
- }
-
- template< class Config >
- template< typename T >
- T Value_impl< Config >::get_value() const
- {
- return internal_::get_value( *this, internal_::Type_to_type< T >() );
- }
-}
-
-#endif
diff --git a/src/json/json_spirit_writer.cpp b/src/json/json_spirit_writer.cpp
deleted file mode 100644
index d24a632cf3..0000000000
--- a/src/json/json_spirit_writer.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#include "json_spirit_writer.h"
-#include "json_spirit_writer_template.h"
-
-void json_spirit::write( const Value& value, std::ostream& os )
-{
- write_stream( value, os, false );
-}
-
-void json_spirit::write_formatted( const Value& value, std::ostream& os )
-{
- write_stream( value, os, true );
-}
-
-std::string json_spirit::write( const Value& value )
-{
- return write_string( value, false );
-}
-
-std::string json_spirit::write_formatted( const Value& value )
-{
- return write_string( value, true );
-}
-
-#ifndef BOOST_NO_STD_WSTRING
-
-void json_spirit::write( const wValue& value, std::wostream& os )
-{
- write_stream( value, os, false );
-}
-
-void json_spirit::write_formatted( const wValue& value, std::wostream& os )
-{
- write_stream( value, os, true );
-}
-
-std::wstring json_spirit::write( const wValue& value )
-{
- return write_string( value, false );
-}
-
-std::wstring json_spirit::write_formatted( const wValue& value )
-{
- return write_string( value, true );
-}
-
-#endif
-
-void json_spirit::write( const mValue& value, std::ostream& os )
-{
- write_stream( value, os, false );
-}
-
-void json_spirit::write_formatted( const mValue& value, std::ostream& os )
-{
- write_stream( value, os, true );
-}
-
-std::string json_spirit::write( const mValue& value )
-{
- return write_string( value, false );
-}
-
-std::string json_spirit::write_formatted( const mValue& value )
-{
- return write_string( value, true );
-}
-
-#ifndef BOOST_NO_STD_WSTRING
-
-void json_spirit::write( const wmValue& value, std::wostream& os )
-{
- write_stream( value, os, false );
-}
-
-void json_spirit::write_formatted( const wmValue& value, std::wostream& os )
-{
- write_stream( value, os, true );
-}
-
-std::wstring json_spirit::write( const wmValue& value )
-{
- return write_string( value, false );
-}
-
-std::wstring json_spirit::write_formatted( const wmValue& value )
-{
- return write_string( value, true );
-}
-
-#endif
diff --git a/src/json/json_spirit_writer.h b/src/json/json_spirit_writer.h
deleted file mode 100644
index 52e14068e7..0000000000
--- a/src/json/json_spirit_writer.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef JSON_SPIRIT_WRITER
-#define JSON_SPIRIT_WRITER
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include "json_spirit_value.h"
-#include <iostream>
-
-namespace json_spirit
-{
- // functions to convert JSON Values to text,
- // the "formatted" versions add whitespace to format the output nicely
-
- void write ( const Value& value, std::ostream& os );
- void write_formatted( const Value& value, std::ostream& os );
- std::string write ( const Value& value );
- std::string write_formatted( const Value& value );
-
-#ifndef BOOST_NO_STD_WSTRING
-
- void write ( const wValue& value, std::wostream& os );
- void write_formatted( const wValue& value, std::wostream& os );
- std::wstring write ( const wValue& value );
- std::wstring write_formatted( const wValue& value );
-
-#endif
-
- void write ( const mValue& value, std::ostream& os );
- void write_formatted( const mValue& value, std::ostream& os );
- std::string write ( const mValue& value );
- std::string write_formatted( const mValue& value );
-
-#ifndef BOOST_NO_STD_WSTRING
-
- void write ( const wmValue& value, std::wostream& os );
- void write_formatted( const wmValue& value, std::wostream& os );
- std::wstring write ( const wmValue& value );
- std::wstring write_formatted( const wmValue& value );
-
-#endif
-}
-
-#endif
diff --git a/src/json/json_spirit_writer_template.h b/src/json/json_spirit_writer_template.h
deleted file mode 100644
index 6b4978a1ff..0000000000
--- a/src/json/json_spirit_writer_template.h
+++ /dev/null
@@ -1,249 +0,0 @@
-#ifndef JSON_SPIRIT_WRITER_TEMPLATE
-#define JSON_SPIRIT_WRITER_TEMPLATE
-
-// Copyright John W. Wilkinson 2007 - 2009.
-// Distributed under the MIT License, see accompanying file LICENSE.txt
-
-// json spirit version 4.03
-
-#include "json_spirit_value.h"
-
-#include <cassert>
-#include <sstream>
-#include <iomanip>
-
-namespace json_spirit
-{
- inline char to_hex_char( unsigned int c )
- {
- assert( c <= 0xF );
-
- const char ch = static_cast< char >( c );
-
- if( ch < 10 ) return '0' + ch;
-
- return 'A' - 10 + ch;
- }
-
- template< class String_type >
- String_type non_printable_to_string( unsigned int c )
- {
- // Silence the warning: typedef ‘Char_type’ locally defined but not used [-Wunused-local-typedefs]
- // typedef typename String_type::value_type Char_type;
-
- String_type result( 6, '\\' );
-
- result[1] = 'u';
-
- result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
- result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
- result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
- result[ 2 ] = to_hex_char( c & 0x000F );
-
- return result;
- }
-
- template< typename Char_type, class String_type >
- bool add_esc_char( Char_type c, String_type& s )
- {
- switch( c )
- {
- case '"': s += to_str< String_type >( "\\\"" ); return true;
- case '\\': s += to_str< String_type >( "\\\\" ); return true;
- case '\b': s += to_str< String_type >( "\\b" ); return true;
- case '\f': s += to_str< String_type >( "\\f" ); return true;
- case '\n': s += to_str< String_type >( "\\n" ); return true;
- case '\r': s += to_str< String_type >( "\\r" ); return true;
- case '\t': s += to_str< String_type >( "\\t" ); return true;
- }
-
- return false;
- }
-
- template< class String_type >
- String_type add_esc_chars( const String_type& s )
- {
- typedef typename String_type::const_iterator Iter_type;
- typedef typename String_type::value_type Char_type;
-
- String_type result;
-
- const Iter_type end( s.end() );
-
- for( Iter_type i = s.begin(); i != end; ++i )
- {
- const Char_type c( *i );
-
- if( add_esc_char( c, result ) ) continue;
-
- const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
-
- if( iswprint( unsigned_c ) )
- {
- result += c;
- }
- else
- {
- result += non_printable_to_string< String_type >( unsigned_c );
- }
- }
-
- return result;
- }
-
- // this class generates the JSON text,
- // it keeps track of the indentation level etc.
- //
- template< class Value_type, class Ostream_type >
- class Generator
- {
- typedef typename Value_type::Config_type Config_type;
- typedef typename Config_type::String_type String_type;
- typedef typename Config_type::Object_type Object_type;
- typedef typename Config_type::Array_type Array_type;
- typedef typename String_type::value_type Char_type;
- typedef typename Object_type::value_type Obj_member_type;
-
- public:
-
- Generator( const Value_type& value, Ostream_type& os, bool pretty )
- : os_( os )
- , indentation_level_( 0 )
- , pretty_( pretty )
- {
- output( value );
- }
-
- private:
-
- void output( const Value_type& value )
- {
- switch( value.type() )
- {
- case obj_type: output( value.get_obj() ); break;
- case array_type: output( value.get_array() ); break;
- case str_type: output( value.get_str() ); break;
- case bool_type: output( value.get_bool() ); break;
- case int_type: output_int( value ); break;
-
- /// Bitcoin: Added std::fixed and changed precision from 16 to 8
- case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8)
- << value.get_real(); break;
-
- case null_type: os_ << "null"; break;
- default: assert( false );
- }
- }
-
- void output( const Object_type& obj )
- {
- output_array_or_obj( obj, '{', '}' );
- }
-
- void output( const Array_type& arr )
- {
- output_array_or_obj( arr, '[', ']' );
- }
-
- void output( const Obj_member_type& member )
- {
- output( Config_type::get_name( member ) ); space();
- os_ << ':'; space();
- output( Config_type::get_value( member ) );
- }
-
- void output_int( const Value_type& value )
- {
- if( value.is_uint64() )
- {
- os_ << value.get_uint64();
- }
- else
- {
- os_ << value.get_int64();
- }
- }
-
- void output( const String_type& s )
- {
- os_ << '"' << add_esc_chars( s ) << '"';
- }
-
- void output( bool b )
- {
- os_ << to_str< String_type >( b ? "true" : "false" );
- }
-
- template< class T >
- void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
- {
- os_ << start_char; new_line();
-
- ++indentation_level_;
-
- for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
- {
- indent(); output( *i );
-
- typename T::const_iterator next = i;
-
- if( ++next != t.end())
- {
- os_ << ',';
- }
-
- new_line();
- }
-
- --indentation_level_;
-
- indent(); os_ << end_char;
- }
-
- void indent()
- {
- if( !pretty_ ) return;
-
- for( int i = 0; i < indentation_level_; ++i )
- {
- os_ << " ";
- }
- }
-
- void space()
- {
- if( pretty_ ) os_ << ' ';
- }
-
- void new_line()
- {
- if( pretty_ ) os_ << '\n';
- }
-
- Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
-
- Ostream_type& os_;
- int indentation_level_;
- bool pretty_;
- };
-
- template< class Value_type, class Ostream_type >
- void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
- {
- Generator< Value_type, Ostream_type >( value, os, pretty );
- }
-
- template< class Value_type >
- typename Value_type::String_type write_string( const Value_type& value, bool pretty )
- {
- typedef typename Value_type::String_type::value_type Char_type;
-
- std::basic_ostringstream< Char_type > os;
-
- write_stream( value, os, pretty );
-
- return os.str();
- }
-}
-
-#endif
diff --git a/src/main.cpp b/src/main.cpp
index 651348300e..b5dd2643d3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -264,9 +264,9 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
}
// Returns time at which to timeout block request (nTime in microseconds)
-int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore)
+int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams)
{
- return nTime + 500000 * Params().GetConsensus().nPowTargetSpacing * (4 + nValidatedQueuedBefore);
+ return nTime + 500000 * consensusParams.nPowTargetSpacing * (4 + nValidatedQueuedBefore);
}
void InitializeNode(NodeId nodeid, const CNode *pnode) {
@@ -296,7 +296,8 @@ void FinalizeNode(NodeId nodeid) {
}
// Requires cs_main.
-void MarkBlockAsReceived(const uint256& hash) {
+// Returns a bool indicating whether we requested this block.
+bool MarkBlockAsReceived(const uint256& hash) {
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first);
@@ -306,11 +307,13 @@ void MarkBlockAsReceived(const uint256& hash) {
state->nBlocksInFlight--;
state->nStallingSince = 0;
mapBlocksInFlight.erase(itInFlight);
+ return true;
}
+ return false;
}
// Requires cs_main.
-void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, CBlockIndex *pindex = NULL) {
+void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Params& consensusParams, CBlockIndex *pindex = NULL) {
CNodeState *state = State(nodeid);
assert(state != NULL);
@@ -318,7 +321,7 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, CBlockIndex *pindex
MarkBlockAsReceived(hash);
int64_t nNow = GetTimeMicros();
- QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders)};
+ QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)};
nQueuedValidatedHeaders += newentry.fValidatedHeaders;
list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
state->nBlocksInFlight++;
@@ -671,14 +674,8 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
- AssertLockHeld(cs_main);
- // Time based nLockTime implemented in 0.1.6
if (tx.nLockTime == 0)
return true;
- if (nBlockHeight == 0)
- nBlockHeight = chainActive.Height();
- if (nBlockTime == 0)
- nBlockTime = GetAdjustedTime();
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
return true;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
@@ -687,10 +684,16 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
}
+bool CheckFinalTx(const CTransaction &tx)
+{
+ AssertLockHeld(cs_main);
+ return IsFinalTx(tx, chainActive.Height() + 1, GetAdjustedTime());
+}
+
/**
* Check transaction inputs to mitigate two
* potential denial-of-service attacks:
- *
+ *
* 1. scriptSigs with extra data stuffed into them,
* not consumed by scriptPubKey (or P2SH script)
* 2. P2SH scripts with a crazy number of expensive
@@ -903,21 +906,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
- //
- // However, IsFinalTx() is confusing... Without arguments, it uses
- // chainActive.Height() to evaluate nLockTime; when a block is accepted,
- // chainActive.Height() is set to the value of nHeight in the block.
- // However, when IsFinalTx() is called within CBlock::AcceptBlock(), the
- // height of the block *being* evaluated is what is used. Thus if we want
- // to know if a transaction can be part of the *next* block, we need to
- // call IsFinalTx() with one more than chainActive.Height().
- //
- // Timestamps on the other hand don't get any special treatment, because we
- // can't know what timestamp the next block will have, and there aren't
- // timestamp applications where it matters.
- if (!IsFinalTx(tx, chainActive.Height() + 1))
- return state.DoS(0,
- error("AcceptToMemoryPool: non-final"),
+ if (!CheckFinalTx(tx))
+ return state.DoS(0, error("AcceptToMemoryPool: non-final"),
REJECT_NONSTANDARD, "non-final");
// is it already in the memory pool?
@@ -1800,7 +1790,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return true;
}
- bool fScriptChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()));
+ bool fScriptChecks = true;
+ if (fCheckpointsEnabled) {
+ CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints());
+ if (pindexLastCheckpoint && pindexLastCheckpoint->GetAncestor(pindex->nHeight) == pindex) {
+ // This block is an ancestor of a checkpoint: disable script checks
+ fScriptChecks = false;
+ }
+ }
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// unless those are already completely spent.
@@ -2158,7 +2155,7 @@ static int64_t nTimeFlush = 0;
static int64_t nTimeChainState = 0;
static int64_t nTimePostConnect = 0;
-/**
+/**
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
@@ -2744,13 +2741,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.Invalid(error("%s: block's timestamp is too early", __func__),
REJECT_INVALID, "time-too-old");
- if(fCheckpointsEnabled)
+ if (fCheckpointsEnabled)
{
- // Check that the block chain matches the known block chain up to a checkpoint
- if (!Checkpoints::CheckBlock(chainParams.Checkpoints(), nHeight, hash))
- return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight),
- REJECT_CHECKPOINT, "checkpoint mismatch");
-
// Don't accept any forks from the main chain prior to last checkpoint
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
@@ -2839,7 +2831,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
return true;
}
-bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp)
+bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp)
{
const CChainParams& chainparams = Params();
AssertLockHeld(cs_main);
@@ -2849,13 +2841,18 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
if (!AcceptBlockHeader(block, state, &pindex))
return false;
- // If we're pruning, ensure that we don't allow a peer to dump a copy
- // of old blocks. But we might need blocks that are not on the main chain
- // to handle a reorg, even if we've processed once.
- if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) {
- // TODO: deal better with duplicate blocks.
- // return state.DoS(20, error("AcceptBlock(): already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString()), REJECT_DUPLICATE, "duplicate");
- return true;
+ // Try to process all requested blocks that we don't have, but only
+ // process an unrequested block if it's new and has enough work to
+ // advance our tip.
+ bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA;
+ bool fHasMoreWork = (chainActive.Tip() ? pindex->nChainWork > chainActive.Tip()->nChainWork : true);
+
+ // TODO: deal better with return value and error conditions for duplicate
+ // and unrequested blocks.
+ if (fAlreadyHave) return true;
+ if (!fRequested) { // If we didn't ask for it:
+ if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned
+ if (!fHasMoreWork) return true; // Don't process less-work chains
}
if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
@@ -2904,21 +2901,22 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
}
-bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
+bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp)
{
// Preliminary checks
bool checked = CheckBlock(*pblock, state);
{
LOCK(cs_main);
- MarkBlockAsReceived(pblock->GetHash());
+ bool fRequested = MarkBlockAsReceived(pblock->GetHash());
+ fRequested |= fForceProcessing;
if (!checked) {
return error("%s: CheckBlock FAILED", __func__);
}
// Store to disk
CBlockIndex *pindex = NULL;
- bool ret = AcceptBlock(*pblock, state, &pindex, dbp);
+ bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp);
if (pindex && pfrom) {
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
}
@@ -3466,7 +3464,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
// process in case the block isn't known yet
if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) {
CValidationState state;
- if (ProcessNewBlock(state, NULL, &block, dbp))
+ if (ProcessNewBlock(state, NULL, &block, true, dbp))
nLoaded++;
if (state.IsError())
break;
@@ -3488,7 +3486,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
head.ToString());
CValidationState dummy;
- if (ProcessNewBlock(dummy, NULL, &block, &it->second))
+ if (ProcessNewBlock(dummy, NULL, &block, true, &it->second))
{
nLoaded++;
queue.push_back(block.GetHash());
@@ -3700,7 +3698,7 @@ void static CheckBlockIndex()
// CAlert
//
-string GetWarnings(string strFor)
+std::string GetWarnings(const std::string& strFor)
{
int nPriority = 0;
string strStatusBar;
@@ -4183,7 +4181,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vToFetch.push_back(inv);
// Mark block as in flight already, even though the actual "getdata" message only goes out
// later (within the same cs_main lock, though).
- MarkBlockAsInFlight(pfrom->GetId(), inv.hash);
+ MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus());
}
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
}
@@ -4268,6 +4266,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LOCK(cs_main);
+ if (IsInitialBlockDownload())
+ return true;
+
CBlockIndex* pindex = NULL;
if (locator.IsNull())
{
@@ -4321,7 +4322,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
mempool.check(pcoinsTip);
RelayTransaction(tx);
vWorkQueue.push_back(inv.hash);
- vEraseQueue.push_back(inv.hash);
LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s: accepted %s (poolsz %u)\n",
pfrom->id, pfrom->cleanSubVer,
@@ -4348,7 +4348,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// anyone relaying LegitTxX banned)
CValidationState stateDummy;
- vEraseQueue.push_back(orphanHash);
if (setMisbehaving.count(fromPeer))
continue;
@@ -4357,6 +4356,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx);
vWorkQueue.push_back(orphanHash);
+ vEraseQueue.push_back(orphanHash);
}
else if (!fMissingInputs2)
{
@@ -4368,8 +4368,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
setMisbehaving.insert(fromPeer);
LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString());
}
- // too-little-fee orphan
+ // Has inputs but not accepted to mempool
+ // Probably non-standard or insufficient fee/priority
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
+ vEraseQueue.push_back(orphanHash);
}
mempool.check(pcoinsTip);
}
@@ -4472,7 +4474,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->AddInventoryKnown(inv);
CValidationState state;
- ProcessNewBlock(state, pfrom, &block);
+ // Process all blocks from whitelisted peers, even if not requested.
+ ProcessNewBlock(state, pfrom, &block, pfrom->fWhitelisted, NULL);
int nDoS;
if (state.IsInvalid(nDoS)) {
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
@@ -5036,7 +5039,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// more quickly than once every 5 minutes, then we'll shorten the download window for this block).
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) {
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
- int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders);
+ int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams);
if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) {
LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow);
queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow;
@@ -5057,7 +5060,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
BOOST_FOREACH(CBlockIndex *pindex, vToDownload) {
vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
- MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex);
+ MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
pindex->nHeight, pto->id);
}
diff --git a/src/main.h b/src/main.h
index 9bf7bbb2f8..abaedae207 100644
--- a/src/main.h
+++ b/src/main.h
@@ -153,10 +153,11 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals);
* @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation.
* @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
* @param[in] pblock The block we want to process.
+ * @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers.
* @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
* @return True if state.IsValid()
*/
-bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
+bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
@@ -189,7 +190,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload();
/** Format a string that describes several potential problems detected by the core */
-std::string GetWarnings(std::string strFor);
+std::string GetWarnings(const std::string& strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false);
/** Find the best known block, and make it the tip of the block chain */
@@ -324,7 +325,18 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state);
*/
bool IsStandardTx(const CTransaction& tx, std::string& reason);
-bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0);
+/**
+ * Check if transaction is final and can be included in a block with the
+ * specified height and time. Consensus critical.
+ */
+bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
+
+/**
+ * Check if transaction will be final in the next block to be created.
+ *
+ * Calls IsFinalTx() with current block height and appropriate block time.
+ */
+bool CheckFinalTx(const CTransaction &tx);
/**
* Closure representing one script verification
@@ -389,8 +401,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
-/** Store block on disk. If dbp is provided, the file is known to already reside on disk */
-bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL);
+/** Store block on disk. If dbp is non-NULL, the file is known to already reside on disk */
+bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
diff --git a/src/miner.cpp b/src/miner.cpp
index 7a57b42e30..f5919ca3af 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -138,6 +138,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1;
+ pblock->nTime = GetAdjustedTime();
CCoinsViewCache view(pcoinsTip);
// Priority order to process transactions
@@ -152,7 +153,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
mi != mempool.mapTx.end(); ++mi)
{
const CTransaction& tx = mi->second.GetTx();
- if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight))
+ if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime))
continue;
COrphan* porphan = NULL;
@@ -433,7 +434,7 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
// Process this block the same as if we had received it from another node
CValidationState state;
- if (!ProcessNewBlock(state, NULL, pblock))
+ if (!ProcessNewBlock(state, NULL, pblock, true, NULL))
return error("BitcoinMiner: ProcessNewBlock, block not accepted");
return true;
diff --git a/src/net.cpp b/src/net.cpp
index 6849d79263..42ac0e50ea 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -107,7 +107,7 @@ boost::condition_variable messageHandlerCondition;
static CNodeSignals g_signals;
CNodeSignals& GetNodeSignals() { return g_signals; }
-void AddOneShot(string strDest)
+void AddOneShot(const std::string& strDest)
{
LOCK(cs_vOneShots);
vOneShots.push_back(strDest);
@@ -1124,7 +1124,7 @@ void ThreadDNSAddressSeed()
vector<CAddress> vAdd;
if (LookupHost(seed.host.c_str(), vIPs))
{
- BOOST_FOREACH(CNetAddr& ip, vIPs)
+ BOOST_FOREACH(const CNetAddr& ip, vIPs)
{
int nOneDay = 24*3600;
CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
@@ -1188,7 +1188,7 @@ void ThreadOpenConnections()
for (int64_t nLoop = 0;; nLoop++)
{
ProcessOneShot();
- BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
+ BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-connect"])
{
CAddress addr;
OpenNetworkConnection(addr, NULL, strAddr.c_str());
@@ -1291,10 +1291,10 @@ void ThreadOpenAddedConnections()
list<string> lAddresses(0);
{
LOCK(cs_vAddedNodes);
- BOOST_FOREACH(string& strAddNode, vAddedNodes)
+ BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
lAddresses.push_back(strAddNode);
}
- BOOST_FOREACH(string& strAddNode, lAddresses) {
+ BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
CAddress addr;
CSemaphoreGrant grant(*semOutbound);
OpenNetworkConnection(addr, &grant, strAddNode.c_str());
@@ -1309,20 +1309,19 @@ void ThreadOpenAddedConnections()
list<string> lAddresses(0);
{
LOCK(cs_vAddedNodes);
- BOOST_FOREACH(string& strAddNode, vAddedNodes)
+ BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
lAddresses.push_back(strAddNode);
}
list<vector<CService> > lservAddressesToAdd(0);
- BOOST_FOREACH(string& strAddNode, lAddresses)
- {
+ BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
vector<CService> vservNode(0);
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
{
lservAddressesToAdd.push_back(vservNode);
{
LOCK(cs_setservAddNodeAddresses);
- BOOST_FOREACH(CService& serv, vservNode)
+ BOOST_FOREACH(const CService& serv, vservNode)
setservAddNodeAddresses.insert(serv);
}
}
@@ -1333,7 +1332,7 @@ void ThreadOpenAddedConnections()
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
- BOOST_FOREACH(CService& addrNode, *(it))
+ BOOST_FOREACH(const CService& addrNode, *(it))
if (pnode->addr == addrNode)
{
it = lservAddressesToAdd.erase(it);
@@ -1363,7 +1362,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
FindNode(addrConnect.ToStringIPPort()))
return false;
- } else if (FindNode(pszDest))
+ } else if (FindNode(std::string(pszDest)))
return false;
CNode* pnode = ConnectNode(addrConnect, pszDest);
@@ -1385,7 +1384,7 @@ void ThreadMessageHandler()
{
boost::mutex condition_mutex;
boost::unique_lock<boost::mutex> lock(condition_mutex);
-
+
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
while (true)
{
@@ -1906,7 +1905,7 @@ bool CAddrDB::Read(CAddrMan& addr)
unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
-CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) :
+CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) :
ssSend(SER_NETWORK, INIT_PROTO_VERSION),
addrKnown(5000, 0.001, insecure_rand()),
setInventoryKnown(SendBufferSize() / 1000)
diff --git a/src/net.h b/src/net.h
index 17502b97eb..938f2376f7 100644
--- a/src/net.h
+++ b/src/net.h
@@ -63,7 +63,7 @@ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ;
unsigned int ReceiveFloodSize();
unsigned int SendBufferSize();
-void AddOneShot(std::string strDest);
+void AddOneShot(const std::string& strDest);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const std::string& addrName);
@@ -321,7 +321,7 @@ public:
// Whether a ping is requested.
bool fPingQueued;
- CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false);
+ CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false);
~CNode();
private:
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 41cc18d3cd..e3cb4e706f 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -35,8 +35,6 @@
#define MSG_NOSIGNAL 0
#endif
-using namespace std;
-
// Settings
static proxyType proxyInfo[NET_MAX];
static proxyType nameProxy;
@@ -597,13 +595,13 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, b
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
{
- string strDest;
+ std::string strDest;
int port = portDefault;
if (outProxyConnectionFailed)
*outProxyConnectionFailed = false;
- SplitHostPort(string(pszDest), port, strDest);
+ SplitHostPort(std::string(pszDest), port, strDest);
proxyType nameProxy;
GetNameProxy(nameProxy);
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 4a1f728e18..581d2321bc 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -265,6 +265,19 @@ void copyEntryData(QAbstractItemView *view, int column, int role)
}
}
+QString getEntryData(QAbstractItemView *view, int column, int role)
+{
+ if(!view || !view->selectionModel())
+ return QString();
+ QModelIndexList selection = view->selectionModel()->selectedRows(column);
+
+ if(!selection.isEmpty()) {
+ // Return first item
+ return (selection.at(0).data(role).toString());
+ }
+ return QString();
+}
+
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter,
QString *selectedSuffixOut)
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index bcbb540c37..55df64a256 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -64,6 +64,14 @@ namespace GUIUtil
*/
void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole);
+ /** Return a field of the currently selected entry as a QString. Does nothing if nothing
+ is selected.
+ @param[in] column Data column to extract from the model
+ @param[in] role Data role to extract from the model
+ @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress
+ */
+ QString getEntryData(QAbstractItemView *view, int column, int role);
+
void setClipboard(const QString& str);
/** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
@@ -205,7 +213,7 @@ namespace GUIUtil
#else
typedef QProgressBar ProgressBar;
#endif
-
+
} // namespace GUIUtil
#endif // BITCOIN_QT_GUIUTIL_H
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 29c971ec79..e99972d498 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -16,15 +16,16 @@
#include "rpcclient.h"
#include "util.h"
-#include "json/json_spirit_value.h"
-
#include <openssl/crypto.h>
+#include "univalue/univalue.h"
+
#ifdef ENABLE_WALLET
#include <db_cxx.h>
#endif
#include <QKeyEvent>
+#include <QMenu>
#include <QScrollBar>
#include <QThread>
#include <QTime>
@@ -167,21 +168,21 @@ void RPCExecutor::request(const QString &command)
std::string strPrint;
// Convert argument list to JSON objects in method-dependent way,
// and pass it along with the method name to the dispatcher.
- json_spirit::Value result = tableRPC.execute(
+ UniValue result = tableRPC.execute(
args[0],
RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));
// Format result reply
- if (result.type() == json_spirit::null_type)
+ if (result.isNull())
strPrint = "";
- else if (result.type() == json_spirit::str_type)
+ else if (result.isStr())
strPrint = result.get_str();
else
- strPrint = write_string(result, true);
+ strPrint = result.write(2);
emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
}
- catch (const json_spirit::Object& objError)
+ catch (UniValue& objError)
{
try // Nice formatting for standard-format error
{
@@ -191,7 +192,7 @@ void RPCExecutor::request(const QString &command)
}
catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message
{ // Show raw JSON object
- emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
+ emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write()));
}
}
catch (const std::exception& e)
@@ -205,7 +206,8 @@ RPCConsole::RPCConsole(QWidget *parent) :
ui(new Ui::RPCConsole),
clientModel(0),
historyPtr(0),
- cachedNodeid(-1)
+ cachedNodeid(-1),
+ contextMenu(0)
{
ui->setupUi(this);
GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this);
@@ -305,10 +307,22 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->peerWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
+ // create context menu actions
+ QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this);
+
+ // create context menu
+ contextMenu = new QMenu();
+ contextMenu->addAction(disconnectAction);
+
+ // context menu signals
+ connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMenu(const QPoint&)));
+ connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode()));
+
// connect the peerWidget selection model to our peerSelected() handler
connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &)));
@@ -659,3 +673,21 @@ void RPCConsole::hideEvent(QHideEvent *event)
// stop PeerTableModel auto refresh
clientModel->getPeerTableModel()->stopAutoRefresh();
}
+
+void RPCConsole::showMenu(const QPoint& point)
+{
+ QModelIndex index = ui->peerWidget->indexAt(point);
+ if (index.isValid())
+ contextMenu->exec(QCursor::pos());
+}
+
+void RPCConsole::disconnectSelectedNode()
+{
+ // Get currently selected peer address
+ QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address);
+ // Find the node, disconnect it and clear the selected node
+ if (CNode *bannedNode = FindNode(strNode.toStdString())) {
+ bannedNode->CloseSocketDisconnect();
+ ui->peerWidget->selectionModel()->clearSelection();
+ }
+}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 8737be35d1..767e9aaeea 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -19,6 +19,7 @@ namespace Ui {
}
QT_BEGIN_NAMESPACE
+class QMenu;
class QItemSelection;
QT_END_NAMESPACE
@@ -57,6 +58,8 @@ private slots:
void resizeEvent(QResizeEvent *event);
void showEvent(QShowEvent *event);
void hideEvent(QHideEvent *event);
+ /** Show custom context menu on Peers tab */
+ void showMenu(const QPoint& point);
public slots:
void clear();
@@ -73,6 +76,8 @@ public slots:
void peerSelected(const QItemSelection &selected, const QItemSelection &deselected);
/** Handle updated peer information */
void peerLayoutChanged();
+ /** Disconnect a selected node on the Peers tab */
+ void disconnectSelectedNode();
signals:
// For RPC command executor
@@ -98,6 +103,7 @@ private:
QStringList history;
int historyPtr;
NodeId cachedNodeid;
+ QMenu *contextMenu;
};
#endif // BITCOIN_QT_RPCCONSOLE_H
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 4fffd03adf..5662b16657 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -26,7 +26,7 @@ using namespace std;
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
AssertLockHeld(cs_main);
- if (!IsFinalTx(wtx, chainActive.Height() + 1))
+ if (!CheckFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height());
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 7f1db58e5d..15d13e9fc9 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -188,7 +188,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.depth = wtx.GetDepthInMainChain();
status.cur_num_blocks = chainActive.Height();
- if (!IsFinalTx(wtx, chainActive.Height() + 1))
+ if (!CheckFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
{
diff --git a/src/rest.cpp b/src/rest.cpp
index 1b7954bbf6..1fce7dfc9c 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -16,10 +16,11 @@
#include <boost/algorithm/string.hpp>
#include <boost/dynamic_bitset.hpp>
+#include "univalue/univalue.h"
+
using namespace std;
-using namespace json_spirit;
-static const int MAX_GETUTXOS_OUTPOINTS = 100; //allow a max of 100 outpoints to be queried at once
+static const int MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
enum RetFormat {
RF_UNDEF,
@@ -61,9 +62,9 @@ public:
string message;
};
-extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
-extern Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
-extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
+extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
+extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
+extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
static RestErr RESTERR(enum HTTPStatusCode status, string message)
{
@@ -221,8 +222,8 @@ static bool rest_block(AcceptedConnection* conn,
}
case RF_JSON: {
- Object objBlock = blockToJSON(block, pblockindex, showTxDetails);
- string strJSON = write_string(Value(objBlock), false) + "\n";
+ UniValue objBlock = blockToJSON(block, pblockindex, showTxDetails);
+ string strJSON = objBlock.write() + "\n";
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
}
@@ -262,13 +263,12 @@ static bool rest_chaininfo(AcceptedConnection* conn,
{
vector<string> params;
const RetFormat rf = ParseDataFormat(params, strURIPart);
-
+
switch (rf) {
case RF_JSON: {
- Array rpcParams;
- Value chainInfoObject = getblockchaininfo(rpcParams, false);
-
- string strJSON = write_string(chainInfoObject, false) + "\n";
+ UniValue rpcParams(UniValue::VARR);
+ UniValue chainInfoObject = getblockchaininfo(rpcParams, false);
+ string strJSON = chainInfoObject.write() + "\n";
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
}
@@ -276,7 +276,7 @@ static bool rest_chaininfo(AcceptedConnection* conn,
throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: json)");
}
}
-
+
// not reached
return true; // continue to process further HTTP reqs on this cxn
}
@@ -317,9 +317,9 @@ static bool rest_tx(AcceptedConnection* conn,
}
case RF_JSON: {
- Object objTx;
+ UniValue objTx(UniValue::VOBJ);
TxToJSON(tx, hashBlock, objTx);
- string strJSON = write_string(Value(objTx), false) + "\n";
+ string strJSON = objTx.write() + "\n";
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
}
@@ -342,18 +342,53 @@ static bool rest_getutxos(AcceptedConnection* conn,
vector<string> params;
enum RetFormat rf = ParseDataFormat(params, strURIPart);
+ vector<string> uriParts;
+ if (params.size() > 0 && params[0].length() > 1)
+ {
+ std::string strUriParams = params[0].substr(1);
+ boost::split(uriParts, strUriParams, boost::is_any_of("/"));
+ }
+
// throw exception in case of a empty request
- if (strRequest.length() == 0)
+ if (strRequest.length() == 0 && uriParts.size() == 0)
throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Error: empty request");
+ bool fInputParsed = false;
bool fCheckMemPool = false;
vector<COutPoint> vOutPoints;
// parse/deserialize input
// input-format = output-format, rest/getutxos/bin requires binary input, gives binary output, ...
-
+
+ if (uriParts.size() > 0)
+ {
+
+ //inputs is sent over URI scheme (/rest/getutxos/checkmempool/txid1-n/txid2-n/...)
+ if (uriParts.size() > 0 && uriParts[0] == "checkmempool")
+ fCheckMemPool = true;
+
+ for (size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++)
+ {
+ uint256 txid;
+ int32_t nOutput;
+ std::string strTxid = uriParts[i].substr(0, uriParts[i].find("-"));
+ std::string strOutput = uriParts[i].substr(uriParts[i].find("-")+1);
+
+ if (!ParseInt32(strOutput, &nOutput) || !IsHex(strTxid))
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
+
+ txid.SetHex(strTxid);
+ vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput));
+ }
+
+ if (vOutPoints.size() > 0)
+ fInputParsed = true;
+ else
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Error: empty request");
+ }
+
string strRequestMutable = strRequest; //convert const string to string for allowing hex to bin converting
-
+
switch (rf) {
case RF_HEX: {
// convert hex to bin, continue then with bin part
@@ -363,11 +398,17 @@ static bool rest_getutxos(AcceptedConnection* conn,
case RF_BINARY: {
try {
- //deserialize
- CDataStream oss(SER_NETWORK, PROTOCOL_VERSION);
- oss << strRequestMutable;
- oss >> fCheckMemPool;
- oss >> vOutPoints;
+ //deserialize only if user sent a request
+ if (strRequestMutable.size() > 0)
+ {
+ if (fInputParsed) //don't allow sending input over URI and HTTP RAW DATA
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Combination of URI scheme inputs and raw post data is not allowed");
+
+ CDataStream oss(SER_NETWORK, PROTOCOL_VERSION);
+ oss << strRequestMutable;
+ oss >> fCheckMemPool;
+ oss >> vOutPoints;
+ }
} catch (const std::ios_base::failure& e) {
// abort in case of unreadable binary data
throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
@@ -376,33 +417,8 @@ static bool rest_getutxos(AcceptedConnection* conn,
}
case RF_JSON: {
- try {
- // parse json request
- Value valRequest;
- if (!read_string(strRequest, valRequest))
- throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
-
- Object jsonObject = valRequest.get_obj();
- const Value& checkMempoolValue = find_value(jsonObject, "checkmempool");
-
- if (!checkMempoolValue.is_null()) {
- fCheckMemPool = checkMempoolValue.get_bool();
- }
- const Value& outpointsValue = find_value(jsonObject, "outpoints");
- if (!outpointsValue.is_null()) {
- Array outPoints = outpointsValue.get_array();
- BOOST_FOREACH (const Value& outPoint, outPoints) {
- Object outpointObject = outPoint.get_obj();
- uint256 txid = ParseHashO(outpointObject, "txid");
- Value nValue = find_value(outpointObject, "n");
- int nOutput = nValue.get_int();
- vOutPoints.push_back(COutPoint(txid, nOutput));
- }
- }
- } catch (...) {
- // return HTTP 500 if there was a json parsing error
- throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
- }
+ if (!fInputParsed)
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Error: empty request");
break;
}
default: {
@@ -476,7 +492,7 @@ static bool rest_getutxos(AcceptedConnection* conn,
}
case RF_JSON: {
- Object objGetUTXOResponse;
+ UniValue objGetUTXOResponse(UniValue::VOBJ);
// pack in some essentials
// use more or less the same output as mentioned in Bip64
@@ -484,15 +500,15 @@ static bool rest_getutxos(AcceptedConnection* conn,
objGetUTXOResponse.push_back(Pair("chaintipHash", chainActive.Tip()->GetBlockHash().GetHex()));
objGetUTXOResponse.push_back(Pair("bitmap", bitmapStringRepresentation));
- Array utxos;
+ UniValue utxos(UniValue::VARR);
BOOST_FOREACH (const CCoin& coin, outs) {
- Object utxo;
+ UniValue utxo(UniValue::VOBJ);
utxo.push_back(Pair("txvers", (int32_t)coin.nTxVer));
utxo.push_back(Pair("height", (int32_t)coin.nHeight));
utxo.push_back(Pair("value", ValueFromAmount(coin.out.nValue)));
// include the script in a json output
- Object o;
+ UniValue o(UniValue::VOBJ);
ScriptPubKeyToJSON(coin.out.scriptPubKey, o, true);
utxo.push_back(Pair("scriptPubKey", o));
utxos.push_back(utxo);
@@ -500,7 +516,7 @@ static bool rest_getutxos(AcceptedConnection* conn,
objGetUTXOResponse.push_back(Pair("utxos", utxos));
// return json string
- string strJSON = write_string(Value(objGetUTXOResponse), false) + "\n";
+ string strJSON = objGetUTXOResponse.write() + "\n";
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
}
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 79528db2fe..e45368cb97 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -13,13 +13,12 @@
#include <stdint.h>
-#include "json/json_spirit_value.h"
+#include "univalue/univalue.h"
-using namespace json_spirit;
using namespace std;
-extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
+extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
+void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
double GetDifficulty(const CBlockIndex* blockindex)
{
@@ -53,9 +52,9 @@ double GetDifficulty(const CBlockIndex* blockindex)
}
-Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
+UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
{
- Object result;
+ UniValue result(UniValue::VOBJ);
result.push_back(Pair("hash", block.GetHash().GetHex()));
int confirmations = -1;
// Only report confirmations if the block is on the main chain
@@ -66,12 +65,12 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDe
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
- Array txs;
+ UniValue txs(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
{
if(txDetails)
{
- Object objTx;
+ UniValue objTx(UniValue::VOBJ);
TxToJSON(tx, uint256(), objTx);
txs.push_back(objTx);
}
@@ -94,7 +93,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDe
}
-Value getblockcount(const Array& params, bool fHelp)
+UniValue getblockcount(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -111,7 +110,7 @@ Value getblockcount(const Array& params, bool fHelp)
return chainActive.Height();
}
-Value getbestblockhash(const Array& params, bool fHelp)
+UniValue getbestblockhash(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -128,7 +127,7 @@ Value getbestblockhash(const Array& params, bool fHelp)
return chainActive.Tip()->GetBlockHash().GetHex();
}
-Value getdifficulty(const Array& params, bool fHelp)
+UniValue getdifficulty(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -146,7 +145,7 @@ Value getdifficulty(const Array& params, bool fHelp)
}
-Value getrawmempool(const Array& params, bool fHelp)
+UniValue getrawmempool(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
@@ -187,12 +186,12 @@ Value getrawmempool(const Array& params, bool fHelp)
if (fVerbose)
{
LOCK(mempool.cs);
- Object o;
+ UniValue o(UniValue::VOBJ);
BOOST_FOREACH(const PAIRTYPE(uint256, CTxMemPoolEntry)& entry, mempool.mapTx)
{
const uint256& hash = entry.first;
const CTxMemPoolEntry& e = entry.second;
- Object info;
+ UniValue info(UniValue::VOBJ);
info.push_back(Pair("size", (int)e.GetTxSize()));
info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
info.push_back(Pair("time", e.GetTime()));
@@ -206,7 +205,13 @@ Value getrawmempool(const Array& params, bool fHelp)
if (mempool.exists(txin.prevout.hash))
setDepends.insert(txin.prevout.hash.ToString());
}
- Array depends(setDepends.begin(), setDepends.end());
+
+ UniValue depends(UniValue::VARR);
+ BOOST_FOREACH(const string& dep, setDepends)
+ {
+ depends.push_back(dep);
+ }
+
info.push_back(Pair("depends", depends));
o.push_back(Pair(hash.ToString(), info));
}
@@ -217,7 +222,7 @@ Value getrawmempool(const Array& params, bool fHelp)
vector<uint256> vtxid;
mempool.queryHashes(vtxid);
- Array a;
+ UniValue a(UniValue::VARR);
BOOST_FOREACH(const uint256& hash, vtxid)
a.push_back(hash.ToString());
@@ -225,7 +230,7 @@ Value getrawmempool(const Array& params, bool fHelp)
}
}
-Value getblockhash(const Array& params, bool fHelp)
+UniValue getblockhash(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -250,7 +255,7 @@ Value getblockhash(const Array& params, bool fHelp)
return pblockindex->GetBlockHash().GetHex();
}
-Value getblock(const Array& params, bool fHelp)
+UniValue getblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -318,7 +323,7 @@ Value getblock(const Array& params, bool fHelp)
return blockToJSON(block, pblockindex);
}
-Value gettxoutsetinfo(const Array& params, bool fHelp)
+UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -342,7 +347,7 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
LOCK(cs_main);
- Object ret;
+ UniValue ret(UniValue::VOBJ);
CCoinsStats stats;
FlushStateToDisk();
@@ -358,7 +363,7 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
return ret;
}
-Value gettxout(const Array& params, bool fHelp)
+UniValue gettxout(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 3)
throw runtime_error(
@@ -398,7 +403,7 @@ Value gettxout(const Array& params, bool fHelp)
LOCK(cs_main);
- Object ret;
+ UniValue ret(UniValue::VOBJ);
std::string strHash = params[0].get_str();
uint256 hash(uint256S(strHash));
@@ -412,14 +417,14 @@ Value gettxout(const Array& params, bool fHelp)
LOCK(mempool.cs);
CCoinsViewMemPool view(pcoinsTip, mempool);
if (!view.GetCoins(hash, coins))
- return Value::null;
+ return NullUniValue;
mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
} else {
if (!pcoinsTip->GetCoins(hash, coins))
- return Value::null;
+ return NullUniValue;
}
if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
- return Value::null;
+ return NullUniValue;
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
CBlockIndex *pindex = it->second;
@@ -429,7 +434,7 @@ Value gettxout(const Array& params, bool fHelp)
else
ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
- Object o;
+ UniValue o(UniValue::VOBJ);
ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
ret.push_back(Pair("scriptPubKey", o));
ret.push_back(Pair("version", coins.nVersion));
@@ -438,7 +443,7 @@ Value gettxout(const Array& params, bool fHelp)
return ret;
}
-Value verifychain(const Array& params, bool fHelp)
+UniValue verifychain(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
throw runtime_error(
@@ -466,7 +471,7 @@ Value verifychain(const Array& params, bool fHelp)
return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
}
-Value getblockchaininfo(const Array& params, bool fHelp)
+UniValue getblockchaininfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -489,7 +494,7 @@ Value getblockchaininfo(const Array& params, bool fHelp)
LOCK(cs_main);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("chain", Params().NetworkIDString()));
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
@@ -524,7 +529,7 @@ struct CompareBlocksByHeight
}
};
-Value getchaintips(const Array& params, bool fHelp)
+UniValue getchaintips(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -576,10 +581,10 @@ Value getchaintips(const Array& params, bool fHelp)
setTips.insert(chainActive.Tip());
/* Construct the output array. */
- Array res;
+ UniValue res(UniValue::VARR);
BOOST_FOREACH(const CBlockIndex* block, setTips)
{
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("height", block->nHeight));
obj.push_back(Pair("hash", block->phashBlock->GetHex()));
@@ -614,7 +619,7 @@ Value getchaintips(const Array& params, bool fHelp)
return res;
}
-Value getmempoolinfo(const Array& params, bool fHelp)
+UniValue getmempoolinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -630,14 +635,14 @@ Value getmempoolinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getmempoolinfo", "")
);
- Object ret;
+ UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("size", (int64_t) mempool.size()));
ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
return ret;
}
-Value invalidateblock(const Array& params, bool fHelp)
+UniValue invalidateblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -672,10 +677,10 @@ Value invalidateblock(const Array& params, bool fHelp)
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
}
- return Value::null;
+ return NullUniValue;
}
-Value reconsiderblock(const Array& params, bool fHelp)
+UniValue reconsiderblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -711,5 +716,5 @@ Value reconsiderblock(const Array& params, bool fHelp)
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
}
- return Value::null;
+ return NullUniValue;
}
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index 4b576b3707..f254da5de0 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -11,8 +11,10 @@
#include <set>
#include <stdint.h>
+#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
+#include "univalue/univalue.h"
+
using namespace std;
-using namespace json_spirit;
class CRPCConvertParam
{
@@ -119,25 +121,32 @@ CRPCConvertTable::CRPCConvertTable()
static CRPCConvertTable rpcCvtTable;
+/** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null)
+ * as well as objects and arrays.
+ */
+UniValue ParseNonRFCJSONValue(const std::string& strVal)
+{
+ UniValue jVal;
+ if (!jVal.read(std::string("[")+strVal+std::string("]")) ||
+ !jVal.isArray() || jVal.size()!=1)
+ throw runtime_error(string("Error parsing JSON:")+strVal);
+ return jVal[0];
+}
+
/** Convert strings to command-specific RPC representation */
-Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
+UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
{
- Array params;
+ UniValue params(UniValue::VARR);
for (unsigned int idx = 0; idx < strParams.size(); idx++) {
const std::string& strVal = strParams[idx];
- // insert string value directly
if (!rpcCvtTable.convert(strMethod, idx)) {
+ // insert string value directly
params.push_back(strVal);
- }
-
- // parse string as JSON, insert bool/number/object/etc. value
- else {
- Value jVal;
- if (!read_string(strVal, jVal))
- throw runtime_error(string("Error parsing JSON:")+strVal);
- params.push_back(jVal);
+ } else {
+ // parse string as JSON, insert bool/number/object/etc. value
+ params.push_back(ParseNonRFCJSONValue(strVal));
}
}
diff --git a/src/rpcclient.h b/src/rpcclient.h
index 42fa2d06fe..d68b4ed6ae 100644
--- a/src/rpcclient.h
+++ b/src/rpcclient.h
@@ -6,10 +6,12 @@
#ifndef BITCOIN_RPCCLIENT_H
#define BITCOIN_RPCCLIENT_H
-#include "json/json_spirit_reader_template.h"
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_writer_template.h"
+#include "univalue/univalue.h"
-json_spirit::Array RPCConvertValues(const std::string& strMethod, const std::vector<std::string>& strParams);
+UniValue RPCConvertValues(const std::string& strMethod, const std::vector<std::string>& strParams);
+/** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null)
+ * as well as objects and arrays.
+ */
+UniValue ParseNonRFCJSONValue(const std::string& strVal);
#endif // BITCOIN_RPCCLIENT_H
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index d58d438573..f332814611 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -24,10 +24,8 @@
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_value.h"
+#include "univalue/univalue.h"
-using namespace json_spirit;
using namespace std;
/**
@@ -35,7 +33,7 @@ using namespace std;
* or from the last difficulty change if 'lookup' is nonpositive.
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
*/
-Value GetNetworkHashPS(int lookup, int height) {
+UniValue GetNetworkHashPS(int lookup, int height) {
CBlockIndex *pb = chainActive.Tip();
if (height >= 0 && height < chainActive.Height())
@@ -72,7 +70,7 @@ Value GetNetworkHashPS(int lookup, int height) {
return (int64_t)(workDiff.getdouble() / timeDiff);
}
-Value getnetworkhashps(const Array& params, bool fHelp)
+UniValue getnetworkhashps(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
throw runtime_error(
@@ -95,7 +93,7 @@ Value getnetworkhashps(const Array& params, bool fHelp)
}
#ifdef ENABLE_WALLET
-Value getgenerate(const Array& params, bool fHelp)
+UniValue getgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -114,7 +112,7 @@ Value getgenerate(const Array& params, bool fHelp)
return GetBoolArg("-gen", false);
}
-Value generate(const Array& params, bool fHelp)
+UniValue generate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 1)
throw runtime_error(
@@ -147,7 +145,7 @@ Value generate(const Array& params, bool fHelp)
nHeightEnd = nHeightStart+nGenerate;
}
unsigned int nExtraNonce = 0;
- Array blockHashes;
+ UniValue blockHashes(UniValue::VARR);
while (nHeight < nHeightEnd)
{
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
@@ -164,7 +162,7 @@ Value generate(const Array& params, bool fHelp)
++pblock->nNonce;
}
CValidationState state;
- if (!ProcessNewBlock(state, NULL, pblock))
+ if (!ProcessNewBlock(state, NULL, pblock, true, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
@@ -173,7 +171,7 @@ Value generate(const Array& params, bool fHelp)
}
-Value setgenerate(const Array& params, bool fHelp)
+UniValue setgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -216,12 +214,12 @@ Value setgenerate(const Array& params, bool fHelp)
mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
- return Value::null;
+ return NullUniValue;
}
#endif
-Value getmininginfo(const Array& params, bool fHelp)
+UniValue getmininginfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -248,7 +246,7 @@ Value getmininginfo(const Array& params, bool fHelp)
LOCK(cs_main);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
@@ -267,7 +265,7 @@ Value getmininginfo(const Array& params, bool fHelp)
// NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
-Value prioritisetransaction(const Array& params, bool fHelp)
+UniValue prioritisetransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
throw runtime_error(
@@ -299,10 +297,10 @@ Value prioritisetransaction(const Array& params, bool fHelp)
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
-static Value BIP22ValidationResult(const CValidationState& state)
+static UniValue BIP22ValidationResult(const CValidationState& state)
{
if (state.IsValid())
- return Value::null;
+ return NullUniValue;
std::string strRejectReason = state.GetRejectReason();
if (state.IsError())
@@ -317,7 +315,7 @@ static Value BIP22ValidationResult(const CValidationState& state)
return "valid?";
}
-Value getblocktemplate(const Array& params, bool fHelp)
+UniValue getblocktemplate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
@@ -382,14 +380,14 @@ Value getblocktemplate(const Array& params, bool fHelp)
LOCK(cs_main);
std::string strMode = "template";
- Value lpval = Value::null;
+ UniValue lpval = NullUniValue;
if (params.size() > 0)
{
- const Object& oparam = params[0].get_obj();
- const Value& modeval = find_value(oparam, "mode");
- if (modeval.type() == str_type)
+ const UniValue& oparam = params[0].get_obj();
+ const UniValue& modeval = find_value(oparam, "mode");
+ if (modeval.isStr())
strMode = modeval.get_str();
- else if (modeval.type() == null_type)
+ else if (modeval.isNull())
{
/* Do nothing */
}
@@ -399,8 +397,8 @@ Value getblocktemplate(const Array& params, bool fHelp)
if (strMode == "proposal")
{
- const Value& dataval = find_value(oparam, "data");
- if (dataval.type() != str_type)
+ const UniValue& dataval = find_value(oparam, "data");
+ if (!dataval.isStr())
throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
CBlock block;
@@ -439,14 +437,14 @@ Value getblocktemplate(const Array& params, bool fHelp)
static unsigned int nTransactionsUpdatedLast;
- if (lpval.type() != null_type)
+ if (!lpval.isNull())
{
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
uint256 hashWatchedChain;
boost::system_time checktxtime;
unsigned int nTransactionsUpdatedLastLP;
- if (lpval.type() == str_type)
+ if (lpval.isStr())
{
// Format: <hashBestChain><nTransactionsUpdatedLast>
std::string lpstr = lpval.get_str();
@@ -520,26 +518,25 @@ Value getblocktemplate(const Array& params, bool fHelp)
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nNonce = 0;
- static const Array aCaps = boost::assign::list_of("proposal");
+ UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
- Array transactions;
+ UniValue transactions(UniValue::VARR);
map<uint256, int64_t> setTxIndex;
int i = 0;
- BOOST_FOREACH (CTransaction& tx, pblock->vtx)
- {
+ BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
uint256 txHash = tx.GetHash();
setTxIndex[txHash] = i++;
if (tx.IsCoinBase())
continue;
- Object entry;
+ UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("data", EncodeHexTx(tx)));
entry.push_back(Pair("hash", txHash.GetHex()));
- Array deps;
+ UniValue deps(UniValue::VARR);
BOOST_FOREACH (const CTxIn &in, tx.vin)
{
if (setTxIndex.count(in.prevout.hash))
@@ -554,12 +551,12 @@ Value getblocktemplate(const Array& params, bool fHelp)
transactions.push_back(entry);
}
- Object aux;
+ UniValue aux(UniValue::VOBJ);
aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
- static Array aMutable;
+ static UniValue aMutable(UniValue::VARR);
if (aMutable.empty())
{
aMutable.push_back("time");
@@ -567,7 +564,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
aMutable.push_back("prevblock");
}
- Object result;
+ UniValue result(UniValue::VOBJ);
result.push_back(Pair("capabilities", aCaps));
result.push_back(Pair("version", pblock->nVersion));
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
@@ -606,7 +603,7 @@ protected:
};
};
-Value submitblock(const Array& params, bool fHelp)
+UniValue submitblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -650,7 +647,7 @@ Value submitblock(const Array& params, bool fHelp)
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(state, NULL, &block);
+ bool fAccepted = ProcessNewBlock(state, NULL, &block, true, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{
@@ -667,7 +664,7 @@ Value submitblock(const Array& params, bool fHelp)
return BIP22ValidationResult(state);
}
-Value estimatefee(const Array& params, bool fHelp)
+UniValue estimatefee(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -686,7 +683,7 @@ Value estimatefee(const Array& params, bool fHelp)
+ HelpExampleCli("estimatefee", "6")
);
- RPCTypeCheck(params, boost::assign::list_of(int_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
int nBlocks = params[0].get_int();
if (nBlocks < 1)
@@ -699,7 +696,7 @@ Value estimatefee(const Array& params, bool fHelp)
return ValueFromAmount(feeRate.GetFeePerK());
}
-Value estimatepriority(const Array& params, bool fHelp)
+UniValue estimatepriority(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -718,7 +715,7 @@ Value estimatepriority(const Array& params, bool fHelp)
+ HelpExampleCli("estimatepriority", "6")
);
- RPCTypeCheck(params, boost::assign::list_of(int_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
int nBlocks = params[0].get_int();
if (nBlocks < 1)
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index f5bef2a077..fe6eb81b84 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -20,10 +20,9 @@
#include <stdint.h>
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_value.h"
-using namespace json_spirit;
+#include "univalue/univalue.h"
+
using namespace std;
/**
@@ -39,7 +38,7 @@ using namespace std;
*
* Or alternatively, create a specific query method for the information.
**/
-Value getinfo(const Array& params, bool fHelp)
+UniValue getinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -78,7 +77,7 @@ Value getinfo(const Array& params, bool fHelp)
proxyType proxy;
GetProxy(NET_IPV4, proxy);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
#ifdef ENABLE_WALLET
@@ -108,7 +107,7 @@ Value getinfo(const Array& params, bool fHelp)
}
#ifdef ENABLE_WALLET
-class DescribeAddressVisitor : public boost::static_visitor<Object>
+class DescribeAddressVisitor : public boost::static_visitor<UniValue>
{
private:
isminetype mine;
@@ -116,10 +115,10 @@ private:
public:
DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
- Object operator()(const CNoDestination &dest) const { return Object(); }
+ UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
- Object operator()(const CKeyID &keyID) const {
- Object obj;
+ UniValue operator()(const CKeyID &keyID) const {
+ UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey;
obj.push_back(Pair("isscript", false));
if (mine == ISMINE_SPENDABLE) {
@@ -130,8 +129,8 @@ public:
return obj;
}
- Object operator()(const CScriptID &scriptID) const {
- Object obj;
+ UniValue operator()(const CScriptID &scriptID) const {
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("isscript", true));
if (mine != ISMINE_NO) {
CScript subscript;
@@ -142,7 +141,7 @@ public:
ExtractDestinations(subscript, whichType, addresses, nRequired);
obj.push_back(Pair("script", GetTxnOutputType(whichType)));
obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
- Array a;
+ UniValue a(UniValue::VARR);
BOOST_FOREACH(const CTxDestination& addr, addresses)
a.push_back(CBitcoinAddress(addr).ToString());
obj.push_back(Pair("addresses", a));
@@ -154,7 +153,7 @@ public:
};
#endif
-Value validateaddress(const Array& params, bool fHelp)
+UniValue validateaddress(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -187,7 +186,7 @@ Value validateaddress(const Array& params, bool fHelp)
CBitcoinAddress address(params[0].get_str());
bool isValid = address.IsValid();
- Object ret;
+ UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("isvalid", isValid));
if (isValid)
{
@@ -203,8 +202,8 @@ Value validateaddress(const Array& params, bool fHelp)
ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
if (mine != ISMINE_NO) {
ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
- Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
- ret.insert(ret.end(), detail.begin(), detail.end());
+ UniValue detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
+ ret.pushKVs(detail);
}
if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
@@ -216,10 +215,10 @@ Value validateaddress(const Array& params, bool fHelp)
/**
* Used by addmultisigaddress / createmultisig:
*/
-CScript _createmultisig_redeemScript(const Array& params)
+CScript _createmultisig_redeemScript(const UniValue& params)
{
int nRequired = params[0].get_int();
- const Array& keys = params[1].get_array();
+ const UniValue& keys = params[1].get_array();
// Gather public keys
if (nRequired < 1)
@@ -277,7 +276,7 @@ CScript _createmultisig_redeemScript(const Array& params)
return result;
}
-Value createmultisig(const Array& params, bool fHelp)
+UniValue createmultisig(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 2)
{
@@ -313,14 +312,14 @@ Value createmultisig(const Array& params, bool fHelp)
CScriptID innerID(inner);
CBitcoinAddress address(innerID);
- Object result;
+ UniValue result(UniValue::VOBJ);
result.push_back(Pair("address", address.ToString()));
result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
return result;
}
-Value verifymessage(const Array& params, bool fHelp)
+UniValue verifymessage(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
throw runtime_error(
@@ -374,7 +373,7 @@ Value verifymessage(const Array& params, bool fHelp)
return (pubkey.GetID() == keyID);
}
-Value setmocktime(const Array& params, bool fHelp)
+UniValue setmocktime(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -390,8 +389,8 @@ Value setmocktime(const Array& params, bool fHelp)
LOCK(cs_main);
- RPCTypeCheck(params, boost::assign::list_of(int_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
SetMockTime(params[0].get_int64());
- return Value::null;
+ return NullUniValue;
}
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index bdee5b9f2e..a36831de2a 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -16,12 +16,11 @@
#include <boost/foreach.hpp>
-#include "json/json_spirit_value.h"
+#include "univalue/univalue.h"
-using namespace json_spirit;
using namespace std;
-Value getconnectioncount(const Array& params, bool fHelp)
+UniValue getconnectioncount(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -39,7 +38,7 @@ Value getconnectioncount(const Array& params, bool fHelp)
return (int)vNodes.size();
}
-Value ping(const Array& params, bool fHelp)
+UniValue ping(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -59,7 +58,7 @@ Value ping(const Array& params, bool fHelp)
pNode->fPingQueued = true;
}
- return Value::null;
+ return NullUniValue;
}
static void CopyNodeStats(std::vector<CNodeStats>& vstats)
@@ -75,7 +74,7 @@ static void CopyNodeStats(std::vector<CNodeStats>& vstats)
}
}
-Value getpeerinfo(const Array& params, bool fHelp)
+UniValue getpeerinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -120,10 +119,10 @@ Value getpeerinfo(const Array& params, bool fHelp)
vector<CNodeStats> vstats;
CopyNodeStats(vstats);
- Array ret;
+ UniValue ret(UniValue::VARR);
BOOST_FOREACH(const CNodeStats& stats, vstats) {
- Object obj;
+ UniValue obj(UniValue::VOBJ);
CNodeStateStats statestats;
bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
obj.push_back(Pair("id", stats.nodeid));
@@ -151,7 +150,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("banscore", statestats.nMisbehavior));
obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
- Array heights;
+ UniValue heights(UniValue::VARR);
BOOST_FOREACH(int height, statestats.vHeightInFlight) {
heights.push_back(height);
}
@@ -165,7 +164,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
return ret;
}
-Value addnode(const Array& params, bool fHelp)
+UniValue addnode(const UniValue& params, bool fHelp)
{
string strCommand;
if (params.size() == 2)
@@ -190,7 +189,7 @@ Value addnode(const Array& params, bool fHelp)
{
CAddress addr;
OpenNetworkConnection(addr, NULL, strNode.c_str());
- return Value::null;
+ return NullUniValue;
}
LOCK(cs_vAddedNodes);
@@ -212,10 +211,10 @@ Value addnode(const Array& params, bool fHelp)
vAddedNodes.erase(it);
}
- return Value::null;
+ return NullUniValue;
}
-Value getaddednodeinfo(const Array& params, bool fHelp)
+UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -254,29 +253,29 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
if (params.size() == 1)
{
LOCK(cs_vAddedNodes);
- BOOST_FOREACH(string& strAddNode, vAddedNodes)
+ BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
laddedNodes.push_back(strAddNode);
}
else
{
string strNode = params[1].get_str();
LOCK(cs_vAddedNodes);
- BOOST_FOREACH(string& strAddNode, vAddedNodes)
+ BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) {
if (strAddNode == strNode)
{
laddedNodes.push_back(strAddNode);
break;
}
+ }
if (laddedNodes.size() == 0)
throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
}
- Array ret;
+ UniValue ret(UniValue::VARR);
if (!fDns)
{
- BOOST_FOREACH(string& strAddNode, laddedNodes)
- {
- Object obj;
+ BOOST_FOREACH (const std::string& strAddNode, laddedNodes) {
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("addednode", strAddNode));
ret.push_back(obj);
}
@@ -284,17 +283,16 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
}
list<pair<string, vector<CService> > > laddedAddreses(0);
- BOOST_FOREACH(string& strAddNode, laddedNodes)
- {
+ BOOST_FOREACH(const std::string& strAddNode, laddedNodes) {
vector<CService> vservNode(0);
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
laddedAddreses.push_back(make_pair(strAddNode, vservNode));
else
{
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("addednode", strAddNode));
obj.push_back(Pair("connected", false));
- Array addresses;
+ UniValue addresses(UniValue::VARR);
obj.push_back(Pair("addresses", addresses));
}
}
@@ -302,17 +300,16 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
LOCK(cs_vNodes);
for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
{
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("addednode", it->first));
- Array addresses;
+ UniValue addresses(UniValue::VARR);
bool fConnected = false;
- BOOST_FOREACH(CService& addrNode, it->second)
- {
+ BOOST_FOREACH(const CService& addrNode, it->second) {
bool fFound = false;
- Object node;
+ UniValue node(UniValue::VOBJ);
node.push_back(Pair("address", addrNode.ToString()));
- BOOST_FOREACH(CNode* pnode, vNodes)
+ BOOST_FOREACH(CNode* pnode, vNodes) {
if (pnode->addr == addrNode)
{
fFound = true;
@@ -320,6 +317,7 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
break;
}
+ }
if (!fFound)
node.push_back(Pair("connected", "false"));
addresses.push_back(node);
@@ -332,7 +330,7 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
return ret;
}
-Value getnettotals(const Array& params, bool fHelp)
+UniValue getnettotals(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 0)
throw runtime_error(
@@ -350,23 +348,23 @@ Value getnettotals(const Array& params, bool fHelp)
+ HelpExampleRpc("getnettotals", "")
);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
obj.push_back(Pair("timemillis", GetTimeMillis()));
return obj;
}
-static Array GetNetworksInfo()
+static UniValue GetNetworksInfo()
{
- Array networks;
+ UniValue networks(UniValue::VARR);
for(int n=0; n<NET_MAX; ++n)
{
enum Network network = static_cast<enum Network>(n);
if(network == NET_UNROUTABLE)
continue;
proxyType proxy;
- Object obj;
+ UniValue obj(UniValue::VOBJ);
GetProxy(network, proxy);
obj.push_back(Pair("name", GetNetworkName(network)));
obj.push_back(Pair("limited", IsLimited(network)));
@@ -378,7 +376,7 @@ static Array GetNetworksInfo()
return networks;
}
-Value getnetworkinfo(const Array& params, bool fHelp)
+UniValue getnetworkinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -418,7 +416,7 @@ Value getnetworkinfo(const Array& params, bool fHelp)
LOCK(cs_main);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("subversion",
FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
@@ -428,12 +426,12 @@ Value getnetworkinfo(const Array& params, bool fHelp)
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("networks", GetNetworksInfo()));
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
- Array localAddresses;
+ UniValue localAddresses(UniValue::VARR);
{
LOCK(cs_mapLocalHost);
BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
{
- Object rec;
+ UniValue rec(UniValue::VOBJ);
rec.push_back(Pair("address", item.first.ToString()));
rec.push_back(Pair("port", item.second.nPort));
rec.push_back(Pair("score", item.second.nScore));
diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp
index 95d6b9e531..090e5ea7f4 100644
--- a/src/rpcprotocol.cpp
+++ b/src/rpcprotocol.cpp
@@ -23,10 +23,10 @@
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/shared_ptr.hpp>
-#include "json/json_spirit_writer_template.h"
+
+#include "univalue/univalue.h"
using namespace std;
-using namespace json_spirit;
//! Number of bytes to allocate and read at most at once in post data
const size_t POST_READ_SIZE = 256 * 1024;
@@ -254,20 +254,20 @@ int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
* http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
*/
-string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
+string JSONRPCRequest(const string& strMethod, const UniValue& params, const UniValue& id)
{
- Object request;
+ UniValue request(UniValue::VOBJ);
request.push_back(Pair("method", strMethod));
request.push_back(Pair("params", params));
request.push_back(Pair("id", id));
- return write_string(Value(request), false) + "\n";
+ return request.write() + "\n";
}
-Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
+UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id)
{
- Object reply;
- if (error.type() != null_type)
- reply.push_back(Pair("result", Value::null));
+ UniValue reply(UniValue::VOBJ);
+ if (!error.isNull())
+ reply.push_back(Pair("result", NullUniValue));
else
reply.push_back(Pair("result", result));
reply.push_back(Pair("error", error));
@@ -275,15 +275,15 @@ Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
return reply;
}
-string JSONRPCReply(const Value& result, const Value& error, const Value& id)
+string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id)
{
- Object reply = JSONRPCReplyObj(result, error, id);
- return write_string(Value(reply), false) + "\n";
+ UniValue reply = JSONRPCReplyObj(result, error, id);
+ return reply.write() + "\n";
}
-Object JSONRPCError(int code, const string& message)
+UniValue JSONRPCError(int code, const string& message)
{
- Object error;
+ UniValue error(UniValue::VOBJ);
error.push_back(Pair("code", code));
error.push_back(Pair("message", message));
return error;
diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h
index 4f3f70fb37..b9fa091955 100644
--- a/src/rpcprotocol.h
+++ b/src/rpcprotocol.h
@@ -15,9 +15,7 @@
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
-#include "json/json_spirit_reader_template.h"
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_writer_template.h"
+#include "univalue/univalue.h"
//! HTTP status codes
enum HTTPStatusCode
@@ -160,9 +158,9 @@ int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto);
int ReadHTTPHeaders(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet);
int ReadHTTPMessage(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet,
std::string& strMessageRet, int nProto, size_t max_size);
-std::string JSONRPCRequest(const std::string& strMethod, const json_spirit::Array& params, const json_spirit::Value& id);
-json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
-std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
-json_spirit::Object JSONRPCError(int code, const std::string& message);
+std::string JSONRPCRequest(const std::string& strMethod, const UniValue& params, const UniValue& id);
+UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id);
+std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
+UniValue JSONRPCError(int code, const std::string& message);
#endif // BITCOIN_RPCPROTOCOL_H
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 3e37b797e8..20394fc2c1 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -25,13 +25,12 @@
#include <stdint.h>
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_value.h"
-using namespace json_spirit;
+#include "univalue/univalue.h"
+
using namespace std;
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
+void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex)
{
txnouttype type;
vector<CTxDestination> addresses;
@@ -49,26 +48,26 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeH
out.push_back(Pair("reqSigs", nRequired));
out.push_back(Pair("type", GetTxnOutputType(type)));
- Array a;
+ UniValue a(UniValue::VARR);
BOOST_FOREACH(const CTxDestination& addr, addresses)
a.push_back(CBitcoinAddress(addr).ToString());
out.push_back(Pair("addresses", a));
}
-void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
+void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
entry.push_back(Pair("txid", tx.GetHash().GetHex()));
entry.push_back(Pair("version", tx.nVersion));
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
- Array vin;
+ UniValue vin(UniValue::VARR);
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
- Object in;
+ UniValue in(UniValue::VOBJ);
if (tx.IsCoinBase())
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
else {
in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
in.push_back(Pair("vout", (int64_t)txin.prevout.n));
- Object o;
+ UniValue o(UniValue::VOBJ);
o.push_back(Pair("asm", txin.scriptSig.ToString()));
o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
in.push_back(Pair("scriptSig", o));
@@ -77,13 +76,13 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
vin.push_back(in);
}
entry.push_back(Pair("vin", vin));
- Array vout;
+ UniValue vout(UniValue::VARR);
for (unsigned int i = 0; i < tx.vout.size(); i++) {
const CTxOut& txout = tx.vout[i];
- Object out;
+ UniValue out(UniValue::VOBJ);
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
out.push_back(Pair("n", (int64_t)i));
- Object o;
+ UniValue o(UniValue::VOBJ);
ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
out.push_back(Pair("scriptPubKey", o));
vout.push_back(out);
@@ -106,7 +105,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
}
}
-Value getrawtransaction(const Array& params, bool fHelp)
+UniValue getrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -190,13 +189,13 @@ Value getrawtransaction(const Array& params, bool fHelp)
if (!fVerbose)
return strHex;
- Object result;
+ UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", strHex));
TxToJSON(tx, hashBlock, result);
return result;
}
-Value gettxoutproof(const Array& params, bool fHelp)
+UniValue gettxoutproof(const UniValue& params, bool fHelp)
{
if (fHelp || (params.size() != 1 && params.size() != 2))
throw runtime_error(
@@ -220,8 +219,9 @@ Value gettxoutproof(const Array& params, bool fHelp)
set<uint256> setTxids;
uint256 oneTxid;
- Array txids = params[0].get_array();
- BOOST_FOREACH(Value& txid, txids) {
+ UniValue txids = params[0].get_array();
+ for (unsigned int idx = 0; idx < txids.size(); idx++) {
+ const UniValue& txid = txids[idx];
if (txid.get_str().length() != 64 || !IsHex(txid.get_str()))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid txid ")+txid.get_str());
uint256 hash(uint256S(txid.get_str()));
@@ -276,7 +276,7 @@ Value gettxoutproof(const Array& params, bool fHelp)
return strHex;
}
-Value verifytxoutproof(const Array& params, bool fHelp)
+UniValue verifytxoutproof(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -293,7 +293,7 @@ Value verifytxoutproof(const Array& params, bool fHelp)
CMerkleBlock merkleBlock;
ssMB >> merkleBlock;
- Array res;
+ UniValue res(UniValue::VARR);
vector<uint256> vMatch;
if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot)
@@ -309,7 +309,7 @@ Value verifytxoutproof(const Array& params, bool fHelp)
return res;
}
-Value createrawtransaction(const Array& params, bool fHelp)
+UniValue createrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 2)
throw runtime_error(
@@ -343,20 +343,21 @@ Value createrawtransaction(const Array& params, bool fHelp)
);
LOCK(cs_main);
- RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ));
- Array inputs = params[0].get_array();
- Object sendTo = params[1].get_obj();
+ UniValue inputs = params[0].get_array();
+ UniValue sendTo = params[1].get_obj();
CMutableTransaction rawTx;
- BOOST_FOREACH(const Value& input, inputs) {
- const Object& o = input.get_obj();
+ for (unsigned int idx = 0; idx < inputs.size(); idx++) {
+ const UniValue& input = inputs[idx];
+ const UniValue& o = input.get_obj();
uint256 txid = ParseHashO(o, "txid");
- const Value& vout_v = find_value(o, "vout");
- if (vout_v.type() != int_type)
+ const UniValue& vout_v = find_value(o, "vout");
+ if (!vout_v.isNum())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
int nOutput = vout_v.get_int();
if (nOutput < 0)
@@ -367,17 +368,18 @@ Value createrawtransaction(const Array& params, bool fHelp)
}
set<CBitcoinAddress> setAddress;
- BOOST_FOREACH(const Pair& s, sendTo) {
- CBitcoinAddress address(s.name_);
+ vector<string> addrList = sendTo.getKeys();
+ BOOST_FOREACH(const string& name_, addrList) {
+ CBitcoinAddress address(name_);
if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
if (setAddress.count(address))
- throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
+ throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
setAddress.insert(address);
CScript scriptPubKey = GetScriptForDestination(address.Get());
- CAmount nAmount = AmountFromValue(s.value_);
+ CAmount nAmount = AmountFromValue(sendTo[name_]);
CTxOut out(nAmount, scriptPubKey);
rawTx.vout.push_back(out);
@@ -386,7 +388,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
return EncodeHexTx(rawTx);
}
-Value decoderawtransaction(const Array& params, bool fHelp)
+UniValue decoderawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -438,20 +440,20 @@ Value decoderawtransaction(const Array& params, bool fHelp)
);
LOCK(cs_main);
- RPCTypeCheck(params, boost::assign::list_of(str_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
CTransaction tx;
if (!DecodeHexTx(tx, params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
- Object result;
+ UniValue result(UniValue::VOBJ);
TxToJSON(tx, uint256(), result);
return result;
}
-Value decodescript(const Array& params, bool fHelp)
+UniValue decodescript(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -477,9 +479,9 @@ Value decodescript(const Array& params, bool fHelp)
);
LOCK(cs_main);
- RPCTypeCheck(params, boost::assign::list_of(str_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
- Object r;
+ UniValue r(UniValue::VOBJ);
CScript script;
if (params[0].get_str().size() > 0){
vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
@@ -494,9 +496,9 @@ Value decodescript(const Array& params, bool fHelp)
}
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
-static void TxInErrorToJSON(const CTxIn& txin, Array& vErrorsRet, const std::string& strMessage)
+static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
{
- Object entry;
+ UniValue entry(UniValue::VOBJ);
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())));
@@ -505,7 +507,7 @@ static void TxInErrorToJSON(const CTxIn& txin, Array& vErrorsRet, const std::str
vErrorsRet.push_back(entry);
}
-Value signrawtransaction(const Array& params, bool fHelp)
+UniValue signrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 4)
throw runtime_error(
@@ -570,7 +572,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
#else
LOCK(cs_main);
#endif
- RPCTypeCheck(params, boost::assign::list_of(str_type)(array_type)(array_type)(str_type), true);
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true);
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
@@ -613,10 +615,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fGivenKeys = false;
CBasicKeyStore tempKeystore;
- if (params.size() > 2 && params[2].type() != null_type) {
+ if (params.size() > 2 && !params[2].isNull()) {
fGivenKeys = true;
- Array keys = params[2].get_array();
- BOOST_FOREACH(Value k, keys) {
+ UniValue keys = params[2].get_array();
+ for (unsigned int idx = 0; idx < keys.size(); idx++) {
+ UniValue k = keys[idx];
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(k.get_str());
if (!fGood)
@@ -633,15 +636,16 @@ Value signrawtransaction(const Array& params, bool fHelp)
#endif
// Add previous txouts given in the RPC call:
- if (params.size() > 1 && params[1].type() != null_type) {
- Array prevTxs = params[1].get_array();
- BOOST_FOREACH(Value& p, prevTxs) {
- if (p.type() != obj_type)
+ if (params.size() > 1 && !params[1].isNull()) {
+ UniValue prevTxs = params[1].get_array();
+ for (unsigned int idx = 0; idx < prevTxs.size(); idx++) {
+ const UniValue& p = prevTxs[idx];
+ if (!p.isObject())
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
- Object prevOut = p.get_obj();
+ UniValue prevOut = p.get_obj();
- RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
+ RPCTypeCheckObj(prevOut, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)("scriptPubKey", UniValue::VSTR));
uint256 txid = ParseHashO(prevOut, "txid");
@@ -669,9 +673,9 @@ Value signrawtransaction(const Array& params, bool fHelp)
// if redeemScript given and not using the local wallet (private keys
// given), add redeemScript to the tempKeystore so it can be signed:
if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
- RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
- Value v = find_value(prevOut, "redeemScript");
- if (!(v == Value::null)) {
+ RPCTypeCheckObj(prevOut, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)("scriptPubKey", UniValue::VSTR)("redeemScript",UniValue::VSTR));
+ UniValue v = find_value(prevOut, "redeemScript");
+ if (!v.isNull()) {
vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
CScript redeemScript(rsData.begin(), rsData.end());
tempKeystore.AddCScript(redeemScript);
@@ -687,7 +691,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
#endif
int nHashType = SIGHASH_ALL;
- if (params.size() > 3 && params[3].type() != null_type) {
+ if (params.size() > 3 && !params[3].isNull()) {
static map<string, int> mapSigHashValues =
boost::assign::map_list_of
(string("ALL"), int(SIGHASH_ALL))
@@ -707,7 +711,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Script verification errors
- Array vErrors;
+ UniValue vErrors(UniValue::VARR);
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
@@ -735,7 +739,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
}
bool fComplete = vErrors.empty();
- Object result;
+ UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
result.push_back(Pair("complete", fComplete));
if (!vErrors.empty()) {
@@ -745,7 +749,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
return result;
}
-Value sendrawtransaction(const Array& params, bool fHelp)
+UniValue sendrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -769,7 +773,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
);
LOCK(cs_main);
- RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
// parse hex string from parameter
CTransaction tx;
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 3f74517a67..3894dd08bb 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -11,6 +11,7 @@
#include "sync.h"
#include "ui_interface.h"
#include "util.h"
+#include "utilmoneystr.h"
#include "utilstrencodings.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
@@ -27,10 +28,10 @@
#include <boost/shared_ptr.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/thread.hpp>
-#include "json/json_spirit_writer_template.h"
+
+#include "univalue/univalue.h"
using namespace boost::asio;
-using namespace json_spirit;
using namespace RPCServer;
using namespace std;
@@ -78,71 +79,67 @@ void RPCServer::OnPostCommand(boost::function<void (const CRPCCommand&)> slot)
g_rpcSignals.PostCommand.connect(boost::bind(slot, _1));
}
-void RPCTypeCheck(const Array& params,
- const list<Value_type>& typesExpected,
+void RPCTypeCheck(const UniValue& params,
+ const list<UniValue::VType>& typesExpected,
bool fAllowNull)
{
unsigned int i = 0;
- BOOST_FOREACH(Value_type t, typesExpected)
+ BOOST_FOREACH(UniValue::VType t, typesExpected)
{
if (params.size() <= i)
break;
- const Value& v = params[i];
- if (!((v.type() == t) || (fAllowNull && (v.type() == null_type))))
+ const UniValue& v = params[i];
+ if (!((v.type() == t) || (fAllowNull && (v.isNull()))))
{
string err = strprintf("Expected type %s, got %s",
- Value_type_name[t], Value_type_name[v.type()]);
+ uvTypeName(t), uvTypeName(v.type()));
throw JSONRPCError(RPC_TYPE_ERROR, err);
}
i++;
}
}
-void RPCTypeCheck(const Object& o,
- const map<string, Value_type>& typesExpected,
+void RPCTypeCheckObj(const UniValue& o,
+ const map<string, UniValue::VType>& typesExpected,
bool fAllowNull)
{
- BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected)
+ BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected)
{
- const Value& v = find_value(o, t.first);
- if (!fAllowNull && v.type() == null_type)
+ const UniValue& v = find_value(o, t.first);
+ if (!fAllowNull && v.isNull())
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
- if (!((v.type() == t.second) || (fAllowNull && (v.type() == null_type))))
+ if (!((v.type() == t.second) || (fAllowNull && (v.isNull()))))
{
string err = strprintf("Expected type %s for %s, got %s",
- Value_type_name[t.second], t.first, Value_type_name[v.type()]);
+ uvTypeName(t.second), t.first, uvTypeName(v.type()));
throw JSONRPCError(RPC_TYPE_ERROR, err);
}
}
}
-static inline int64_t roundint64(double d)
-{
- return (int64_t)(d > 0 ? d + 0.5 : d - 0.5);
-}
-
-CAmount AmountFromValue(const Value& value)
+CAmount AmountFromValue(const UniValue& value)
{
- double dAmount = value.get_real();
- if (dAmount <= 0.0 || dAmount > 21000000.0)
+ if (!value.isReal() && !value.isNum())
+ throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number");
+ CAmount amount;
+ if (!ParseMoney(value.getValStr(), amount))
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
- CAmount nAmount = roundint64(dAmount * COIN);
- if (!MoneyRange(nAmount))
- throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
- return nAmount;
+ if (!MoneyRange(amount))
+ throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
+ return amount;
}
-Value ValueFromAmount(const CAmount& amount)
+UniValue ValueFromAmount(const CAmount& amount)
{
- return (double)amount / (double)COIN;
+ return UniValue(UniValue::VREAL, FormatMoney(amount));
}
-uint256 ParseHashV(const Value& v, string strName)
+uint256 ParseHashV(const UniValue& v, string strName)
{
string strHex;
- if (v.type() == str_type)
+ if (v.isStr())
strHex = v.get_str();
if (!IsHex(strHex)) // Note: IsHex("") is false
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
@@ -150,20 +147,20 @@ uint256 ParseHashV(const Value& v, string strName)
result.SetHex(strHex);
return result;
}
-uint256 ParseHashO(const Object& o, string strKey)
+uint256 ParseHashO(const UniValue& o, string strKey)
{
return ParseHashV(find_value(o, strKey), strKey);
}
-vector<unsigned char> ParseHexV(const Value& v, string strName)
+vector<unsigned char> ParseHexV(const UniValue& v, string strName)
{
string strHex;
- if (v.type() == str_type)
+ if (v.isStr())
strHex = v.get_str();
if (!IsHex(strHex))
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
return ParseHex(strHex);
}
-vector<unsigned char> ParseHexO(const Object& o, string strKey)
+vector<unsigned char> ParseHexO(const UniValue& o, string strKey)
{
return ParseHexV(find_value(o, strKey), strKey);
}
@@ -173,7 +170,7 @@ vector<unsigned char> ParseHexO(const Object& o, string strKey)
* Note: This interface may still be subject to change.
*/
-string CRPCTable::help(string strCommand) const
+std::string CRPCTable::help(const std::string& strCommand) const
{
string strRet;
string category;
@@ -195,7 +192,7 @@ string CRPCTable::help(string strCommand) const
continue;
try
{
- Array params;
+ UniValue params;
rpcfn_type pfn = pcmd->actor;
if (setDone.insert(pfn).second)
(*pfn)(params, true);
@@ -228,7 +225,7 @@ string CRPCTable::help(string strCommand) const
return strRet;
}
-Value help(const Array& params, bool fHelp)
+UniValue help(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
@@ -248,7 +245,7 @@ Value help(const Array& params, bool fHelp)
}
-Value stop(const Array& params, bool fHelp)
+UniValue stop(const UniValue& params, bool fHelp)
{
// Accept the deprecated and ignored 'detach' boolean argument
if (fHelp || params.size() > 1)
@@ -391,7 +388,7 @@ CRPCTable::CRPCTable()
}
}
-const CRPCCommand *CRPCTable::operator[](string name) const
+const CRPCCommand *CRPCTable::operator[](const std::string& name) const
{
map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
if (it == mapCommands.end())
@@ -410,14 +407,14 @@ bool HTTPAuthorized(map<string, string>& mapHeaders)
return TimingResistantEqual(strUserPass, strRPCUserColonPass);
}
-void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
+void ErrorReply(std::ostream& stream, const UniValue& objError, const UniValue& id)
{
// Send error reply from json-rpc error object
int nStatus = HTTP_INTERNAL_SERVER_ERROR;
int code = find_value(objError, "code").get_int();
if (code == RPC_INVALID_REQUEST) nStatus = HTTP_BAD_REQUEST;
else if (code == RPC_METHOD_NOT_FOUND) nStatus = HTTP_NOT_FOUND;
- string strReply = JSONRPCReply(Value::null, objError, id);
+ string strReply = JSONRPCReply(NullUniValue, objError, id);
stream << HTTPReply(nStatus, strReply, false) << std::flush;
}
@@ -824,76 +821,76 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
class JSONRequest
{
public:
- Value id;
+ UniValue id;
string strMethod;
- Array params;
+ UniValue params;
- JSONRequest() { id = Value::null; }
- void parse(const Value& valRequest);
+ JSONRequest() { id = NullUniValue; }
+ void parse(const UniValue& valRequest);
};
-void JSONRequest::parse(const Value& valRequest)
+void JSONRequest::parse(const UniValue& valRequest)
{
// Parse request
- if (valRequest.type() != obj_type)
+ if (!valRequest.isObject())
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
- const Object& request = valRequest.get_obj();
+ const UniValue& request = valRequest.get_obj();
// Parse id now so errors from here on will have the id
id = find_value(request, "id");
// Parse method
- Value valMethod = find_value(request, "method");
- if (valMethod.type() == null_type)
+ UniValue valMethod = find_value(request, "method");
+ if (valMethod.isNull())
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
- if (valMethod.type() != str_type)
+ if (!valMethod.isStr())
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getblocktemplate")
LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
// Parse params
- Value valParams = find_value(request, "params");
- if (valParams.type() == array_type)
+ UniValue valParams = find_value(request, "params");
+ if (valParams.isArray())
params = valParams.get_array();
- else if (valParams.type() == null_type)
- params = Array();
+ else if (valParams.isNull())
+ params = UniValue(UniValue::VARR);
else
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array");
}
-static Object JSONRPCExecOne(const Value& req)
+static UniValue JSONRPCExecOne(const UniValue& req)
{
- Object rpc_result;
+ UniValue rpc_result(UniValue::VOBJ);
JSONRequest jreq;
try {
jreq.parse(req);
- Value result = tableRPC.execute(jreq.strMethod, jreq.params);
- rpc_result = JSONRPCReplyObj(result, Value::null, jreq.id);
+ UniValue result = tableRPC.execute(jreq.strMethod, jreq.params);
+ rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
}
- catch (const Object& objError)
+ catch (const UniValue& objError)
{
- rpc_result = JSONRPCReplyObj(Value::null, objError, jreq.id);
+ rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
}
catch (const std::exception& e)
{
- rpc_result = JSONRPCReplyObj(Value::null,
+ rpc_result = JSONRPCReplyObj(NullUniValue,
JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
}
return rpc_result;
}
-static string JSONRPCExecBatch(const Array& vReq)
+static string JSONRPCExecBatch(const UniValue& vReq)
{
- Array ret;
+ UniValue ret(UniValue::VARR);
for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
- return write_string(Value(ret), false) + "\n";
+ return ret.write() + "\n";
}
static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
@@ -924,8 +921,8 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
try
{
// Parse request
- Value valRequest;
- if (!read_string(strRequest, valRequest))
+ UniValue valRequest;
+ if (!valRequest.read(strRequest))
throw JSONRPCError(RPC_PARSE_ERROR, "Parse error");
// Return immediately if in warmup
@@ -938,23 +935,23 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
string strReply;
// singleton request
- if (valRequest.type() == obj_type) {
+ if (valRequest.isObject()) {
jreq.parse(valRequest);
- Value result = tableRPC.execute(jreq.strMethod, jreq.params);
+ UniValue result = tableRPC.execute(jreq.strMethod, jreq.params);
// Send reply
- strReply = JSONRPCReply(result, Value::null, jreq.id);
+ strReply = JSONRPCReply(result, NullUniValue, jreq.id);
// array of requests
- } else if (valRequest.type() == array_type)
+ } else if (valRequest.isArray())
strReply = JSONRPCExecBatch(valRequest.get_array());
else
throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error");
conn->stream() << HTTPReplyHeader(HTTP_OK, fRun, strReply.size()) << strReply << std::flush;
}
- catch (const Object& objError)
+ catch (const UniValue& objError)
{
ErrorReply(conn->stream(), objError, jreq.id);
return false;
@@ -1004,7 +1001,7 @@ void ServiceConnection(AcceptedConnection *conn)
}
}
-json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array &params) const
+UniValue CRPCTable::execute(const std::string &strMethod, const UniValue &params) const
{
// Find method
const CRPCCommand *pcmd = tableRPC[strMethod];
@@ -1026,11 +1023,13 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
g_rpcSignals.PostCommand(*pcmd);
}
-std::string HelpExampleCli(string methodname, string args){
+std::string HelpExampleCli(const std::string& methodname, const std::string& args)
+{
return "> bitcoin-cli " + methodname + " " + args + "\n";
}
-std::string HelpExampleRpc(string methodname, string args){
+std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
+{
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
}
diff --git a/src/rpcserver.h b/src/rpcserver.h
index 30a5b28db7..7b462a8b79 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -15,9 +15,9 @@
#include <stdint.h>
#include <string>
-#include "json/json_spirit_reader_template.h"
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_writer_template.h"
+#include <boost/function.hpp>
+
+#include "univalue/univalue.h"
class CRPCCommand;
@@ -55,7 +55,7 @@ void StopRPCThreads();
/** Query whether RPC is running */
bool IsRPCRunning();
-/**
+/**
* Set the RPC warmup status. When this is done, all RPC calls will error out
* immediately with RPC_IN_WARMUP.
*/
@@ -71,14 +71,15 @@ bool RPCIsInWarmup(std::string *statusOut);
* the right number of arguments are passed, just that any passed are the correct type.
* Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type));
*/
-void RPCTypeCheck(const json_spirit::Array& params,
- const std::list<json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
-/**
- * Check for expected keys/value types in an Object.
- * Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type));
- */
-void RPCTypeCheck(const json_spirit::Object& o,
- const std::map<std::string, json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
+void RPCTypeCheck(const UniValue& params,
+ const std::list<UniValue::VType>& typesExpected, bool fAllowNull=false);
+
+/*
+ Check for expected keys/value types in an Object.
+ Use like: RPCTypeCheckObj(object, boost::assign::map_list_of("name", str_type)("value", int_type));
+*/
+void RPCTypeCheckObj(const UniValue& o,
+ const std::map<std::string, UniValue::VType>& typesExpected, bool fAllowNull=false);
/**
* Run func nSeconds from now. Uses boost deadline timers.
@@ -89,7 +90,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
//! Convert boost::asio address to CNetAddr
extern CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address);
-typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
+typedef UniValue(*rpcfn_type)(const UniValue& params, bool fHelp);
class CRPCCommand
{
@@ -109,17 +110,17 @@ private:
std::map<std::string, const CRPCCommand*> mapCommands;
public:
CRPCTable();
- const CRPCCommand* operator[](std::string name) const;
- std::string help(std::string name) const;
+ const CRPCCommand* operator[](const std::string& name) const;
+ std::string help(const std::string& name) const;
/**
* Execute a method.
* @param method Method to execute
- * @param params Array of arguments (JSON objects)
+ * @param params UniValue Array of arguments (JSON objects)
* @returns Result of the call.
- * @throws an exception (json_spirit::Value) when an error happens.
+ * @throws an exception (UniValue) when an error happens.
*/
- json_spirit::Value execute(const std::string &method, const json_spirit::Array &params) const;
+ UniValue execute(const std::string &method, const UniValue &params) const;
};
extern const CRPCTable tableRPC;
@@ -128,113 +129,113 @@ extern const CRPCTable tableRPC;
* Utilities: convert hex-encoded Values
* (throws error if not hex).
*/
-extern uint256 ParseHashV(const json_spirit::Value& v, std::string strName);
-extern uint256 ParseHashO(const json_spirit::Object& o, std::string strKey);
-extern std::vector<unsigned char> ParseHexV(const json_spirit::Value& v, std::string strName);
-extern std::vector<unsigned char> ParseHexO(const json_spirit::Object& o, std::string strKey);
+extern uint256 ParseHashV(const UniValue& v, std::string strName);
+extern uint256 ParseHashO(const UniValue& o, std::string strKey);
+extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
+extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
extern void InitRPCMining();
extern void ShutdownRPCMining();
extern int64_t nWalletUnlockTime;
-extern CAmount AmountFromValue(const json_spirit::Value& value);
-extern json_spirit::Value ValueFromAmount(const CAmount& amount);
+extern CAmount AmountFromValue(const UniValue& value);
+extern UniValue ValueFromAmount(const CAmount& amount);
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
extern std::string HelpRequiringPassphrase();
-extern std::string HelpExampleCli(std::string methodname, std::string args);
-extern std::string HelpExampleRpc(std::string methodname, std::string args);
+extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
+extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
extern void EnsureWalletIsUnlocked();
-extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp
-extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp);
-
-extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp
-extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value importaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp);
-
-extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHelp); // in rpcmining.cpp
-extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value generate(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value prioritisetransaction(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value estimatefee(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value estimatepriority(const json_spirit::Array& params, bool fHelp);
-
-extern json_spirit::Value getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp
-extern json_spirit::Value getaccountaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getrawchangeaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value setaccount(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getaccount(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getaddressesbyaccount(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value sendtoaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value signmessage(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value verifymessage(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getreceivedbyaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getreceivedbyaccount(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getbalance(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getunconfirmedbalance(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value movecmd(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value sendfrom(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value sendmany(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value addmultisigaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value createmultisig(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listreceivedbyaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listreceivedbyaccount(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listtransactions(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listaddressgroupings(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listaccounts(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listsinceblock(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value gettransaction(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value backupwallet(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value keypoolrefill(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value walletpassphrase(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value walletpassphrasechange(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value walletlock(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value encryptwallet(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value validateaddress(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getinfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getwalletinfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getblockchaininfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value setmocktime(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value resendwallettransactions(const json_spirit::Array& params, bool fHelp);
-
-extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
-extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value lockunspent(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listlockunspent(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value createrawtransaction(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value decoderawtransaction(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value decodescript(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value gettxoutproof(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value verifytxoutproof(const json_spirit::Array& params, bool fHelp);
-
-extern json_spirit::Value getblockcount(const json_spirit::Array& params, bool fHelp); // in rpcblockchain.cpp
-extern json_spirit::Value getbestblockhash(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getdifficulty(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value settxfee(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getmempoolinfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getrawmempool(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool fHelp);
-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);
-extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value reconsiderblock(const json_spirit::Array& params, bool fHelp);
+extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rpcnet.cpp
+extern UniValue getpeerinfo(const UniValue& params, bool fHelp);
+extern UniValue ping(const UniValue& params, bool fHelp);
+extern UniValue addnode(const UniValue& params, bool fHelp);
+extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp);
+extern UniValue getnettotals(const UniValue& params, bool fHelp);
+
+extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
+extern UniValue importprivkey(const UniValue& params, bool fHelp);
+extern UniValue importaddress(const UniValue& params, bool fHelp);
+extern UniValue dumpwallet(const UniValue& params, bool fHelp);
+extern UniValue importwallet(const UniValue& params, bool fHelp);
+
+extern UniValue getgenerate(const UniValue& params, bool fHelp); // in rpcmining.cpp
+extern UniValue setgenerate(const UniValue& params, bool fHelp);
+extern UniValue generate(const UniValue& params, bool fHelp);
+extern UniValue getnetworkhashps(const UniValue& params, bool fHelp);
+extern UniValue getmininginfo(const UniValue& params, bool fHelp);
+extern UniValue prioritisetransaction(const UniValue& params, bool fHelp);
+extern UniValue getblocktemplate(const UniValue& params, bool fHelp);
+extern UniValue submitblock(const UniValue& params, bool fHelp);
+extern UniValue estimatefee(const UniValue& params, bool fHelp);
+extern UniValue estimatepriority(const UniValue& params, bool fHelp);
+
+extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
+extern UniValue getaccountaddress(const UniValue& params, bool fHelp);
+extern UniValue getrawchangeaddress(const UniValue& params, bool fHelp);
+extern UniValue setaccount(const UniValue& params, bool fHelp);
+extern UniValue getaccount(const UniValue& params, bool fHelp);
+extern UniValue getaddressesbyaccount(const UniValue& params, bool fHelp);
+extern UniValue sendtoaddress(const UniValue& params, bool fHelp);
+extern UniValue signmessage(const UniValue& params, bool fHelp);
+extern UniValue verifymessage(const UniValue& params, bool fHelp);
+extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp);
+extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp);
+extern UniValue getbalance(const UniValue& params, bool fHelp);
+extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp);
+extern UniValue movecmd(const UniValue& params, bool fHelp);
+extern UniValue sendfrom(const UniValue& params, bool fHelp);
+extern UniValue sendmany(const UniValue& params, bool fHelp);
+extern UniValue addmultisigaddress(const UniValue& params, bool fHelp);
+extern UniValue createmultisig(const UniValue& params, bool fHelp);
+extern UniValue listreceivedbyaddress(const UniValue& params, bool fHelp);
+extern UniValue listreceivedbyaccount(const UniValue& params, bool fHelp);
+extern UniValue listtransactions(const UniValue& params, bool fHelp);
+extern UniValue listaddressgroupings(const UniValue& params, bool fHelp);
+extern UniValue listaccounts(const UniValue& params, bool fHelp);
+extern UniValue listsinceblock(const UniValue& params, bool fHelp);
+extern UniValue gettransaction(const UniValue& params, bool fHelp);
+extern UniValue backupwallet(const UniValue& params, bool fHelp);
+extern UniValue keypoolrefill(const UniValue& params, bool fHelp);
+extern UniValue walletpassphrase(const UniValue& params, bool fHelp);
+extern UniValue walletpassphrasechange(const UniValue& params, bool fHelp);
+extern UniValue walletlock(const UniValue& params, bool fHelp);
+extern UniValue encryptwallet(const UniValue& params, bool fHelp);
+extern UniValue validateaddress(const UniValue& params, bool fHelp);
+extern UniValue getinfo(const UniValue& params, bool fHelp);
+extern UniValue getwalletinfo(const UniValue& params, bool fHelp);
+extern UniValue getblockchaininfo(const UniValue& params, bool fHelp);
+extern UniValue getnetworkinfo(const UniValue& params, bool fHelp);
+extern UniValue setmocktime(const UniValue& params, bool fHelp);
+extern UniValue resendwallettransactions(const UniValue& params, bool fHelp);
+
+extern UniValue getrawtransaction(const UniValue& params, bool fHelp); // in rcprawtransaction.cpp
+extern UniValue listunspent(const UniValue& params, bool fHelp);
+extern UniValue lockunspent(const UniValue& params, bool fHelp);
+extern UniValue listlockunspent(const UniValue& params, bool fHelp);
+extern UniValue createrawtransaction(const UniValue& params, bool fHelp);
+extern UniValue decoderawtransaction(const UniValue& params, bool fHelp);
+extern UniValue decodescript(const UniValue& params, bool fHelp);
+extern UniValue signrawtransaction(const UniValue& params, bool fHelp);
+extern UniValue sendrawtransaction(const UniValue& params, bool fHelp);
+extern UniValue gettxoutproof(const UniValue& params, bool fHelp);
+extern UniValue verifytxoutproof(const UniValue& params, bool fHelp);
+
+extern UniValue getblockcount(const UniValue& params, bool fHelp); // in rpcblockchain.cpp
+extern UniValue getbestblockhash(const UniValue& params, bool fHelp);
+extern UniValue getdifficulty(const UniValue& params, bool fHelp);
+extern UniValue settxfee(const UniValue& params, bool fHelp);
+extern UniValue getmempoolinfo(const UniValue& params, bool fHelp);
+extern UniValue getrawmempool(const UniValue& params, bool fHelp);
+extern UniValue getblockhash(const UniValue& params, bool fHelp);
+extern UniValue getblock(const UniValue& params, bool fHelp);
+extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp);
+extern UniValue gettxout(const UniValue& params, bool fHelp);
+extern UniValue verifychain(const UniValue& params, bool fHelp);
+extern UniValue getchaintips(const UniValue& params, bool fHelp);
+extern UniValue invalidateblock(const UniValue& params, bool fHelp);
+extern UniValue reconsiderblock(const UniValue& params, bool fHelp);
// in rest.cpp
extern bool HTTPReq_REST(AcceptedConnection *conn,
diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp
index 642ce13bcd..703cf307d1 100644
--- a/src/test/Checkpoints_tests.cpp
+++ b/src/test/Checkpoints_tests.cpp
@@ -21,21 +21,7 @@ BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(sanity)
{
const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
- uint256 p11111 = uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d");
- uint256 p134444 = uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe");
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111, p11111));
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444, p134444));
-
-
- // Wrong hashes at checkpoints should fail:
- BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 11111, p134444));
- BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 134444, p11111));
-
- // ... but any hash not at a checkpoint should succeed:
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111+1, p134444));
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444+1, p11111));
-
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
-}
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index f07dd7a7db..9e74f5f427 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -17,23 +17,20 @@
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
-#include "json/json_spirit_reader_template.h"
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_writer_template.h"
-using namespace json_spirit;
-extern Array read_json(const std::string& jsondata);
+#include "univalue/univalue.h"
+
+extern UniValue read_json(const std::string& jsondata);
BOOST_FIXTURE_TEST_SUITE(base58_tests, BasicTestingSetup)
// Goal: test low-level base58 encoding functionality
BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
- Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- std::string strTest = write_string(tv, false);
+ UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
if (test.size() < 2) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@@ -50,13 +47,12 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
// Goal: test low-level base58 decoding functionality
BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
{
- Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
+ UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
std::vector<unsigned char> result;
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- std::string strTest = write_string(tv, false);
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
if (test.size() < 2) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@@ -124,16 +120,15 @@ public:
// Goal: check that parsed keys match test payload
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
- Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
+ UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
SelectParams(CBaseChainParams::MAIN);
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- std::string strTest = write_string(tv, false);
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
if (test.size() < 3) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@@ -141,7 +136,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
}
std::string exp_base58string = test[0].get_str();
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
- const Object &metadata = test[2].get_obj();
+ const UniValue &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
if (isTestnet)
@@ -183,12 +178,12 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
// Goal: check that generated keys match test vectors
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
- Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
+ UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
std::vector<unsigned char> result;
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- std::string strTest = write_string(tv, false);
+
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
if (test.size() < 3) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@@ -196,7 +191,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
}
std::string exp_base58string = test[0].get_str();
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
- const Object &metadata = test[2].get_obj();
+ const UniValue &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
if (isTestnet)
@@ -251,15 +246,14 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
// Goal: check that base58 parsing code is robust against a variety of corrupted data
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
- Array tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
+ UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- std::string strTest = write_string(tv, false);
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index b6365b1b3a..212be0d2d6 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -74,6 +74,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->nVersion = 1;
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
CMutableTransaction txCoinbase(pblock->vtx[0]);
+ txCoinbase.nVersion = 1;
txCoinbase.vin[0].scriptSig = CScript();
txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
@@ -84,7 +85,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
pblock->nNonce = blockinfo[i].nonce;
CValidationState state;
- BOOST_CHECK(ProcessNewBlock(state, NULL, pblock));
+ BOOST_CHECK(ProcessNewBlock(state, NULL, pblock, true, NULL));
BOOST_CHECK(state.IsValid());
pblock->hashPrevBlock = pblock->GetHash();
}
@@ -223,7 +224,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = chainActive.Tip()->nHeight+1;
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(!IsFinalTx(tx, chainActive.Tip()->nHeight + 1));
+ BOOST_CHECK(!CheckFinalTx(tx));
// time locked
tx2.vin.resize(1);
@@ -237,7 +238,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx2.nLockTime = chainActive.Tip()->GetMedianTimePast()+1;
hash = tx2.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx2, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(!IsFinalTx(tx2));
+ BOOST_CHECK(!CheckFinalTx(tx2));
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
@@ -249,8 +250,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
chainActive.Tip()->nHeight++;
SetMockTime(chainActive.Tip()->GetMedianTimePast()+2);
- BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 1));
- BOOST_CHECK(IsFinalTx(tx2));
+ // FIXME: we should *actually* create a new block so the following test
+ // works; CheckFinalTx() isn't fooled by monkey-patching nHeight.
+ //BOOST_CHECK(CheckFinalTx(tx));
+ //BOOST_CHECK(CheckFinalTx(tx2));
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3);
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 45cb551d04..08f988fdbf 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -13,35 +13,36 @@
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
+#include "univalue/univalue.h"
+
using namespace std;
-using namespace json_spirit;
-Array
+UniValue
createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
{
- Array result;
+ UniValue result(UniValue::VARR);
result.push_back(nRequired);
- Array addresses;
+ UniValue addresses(UniValue::VARR);
if (address1) addresses.push_back(address1);
if (address2) addresses.push_back(address2);
result.push_back(addresses);
return result;
}
-Value CallRPC(string args)
+UniValue CallRPC(string args)
{
vector<string> vArgs;
boost::split(vArgs, args, boost::is_any_of(" \t"));
string strMethod = vArgs[0];
vArgs.erase(vArgs.begin());
- Array params = RPCConvertValues(strMethod, vArgs);
+ UniValue params = RPCConvertValues(strMethod, vArgs);
rpcfn_type method = tableRPC[strMethod]->actor;
try {
- Value result = (*method)(params, false);
+ UniValue result = (*method)(params, false);
return result;
}
- catch (const Object& objError) {
+ catch (const UniValue& objError) {
throw runtime_error(find_value(objError, "message").get_str());
}
}
@@ -52,7 +53,7 @@ BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup)
BOOST_AUTO_TEST_CASE(rpc_rawparams)
{
// Test raw transaction API argument handling
- Value r;
+ UniValue r;
BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error);
BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error);
@@ -92,7 +93,7 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_AUTO_TEST_CASE(rpc_rawsign)
{
- Value r;
+ UniValue r;
// input is a 1-of-2 multisig (so is output):
string prevout =
"[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
@@ -111,25 +112,28 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign)
BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
{
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(0LL), false), "0.00000000");
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(1LL), false), "0.00000001");
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(17622195LL), false), "0.17622195");
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(50000000LL), false), "0.50000000");
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(89898989LL), false), "0.89898989");
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(100000000LL), false), "1.00000000");
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(2099999999999990LL), false), "20999999.99999990");
- BOOST_CHECK_EQUAL(write_string(ValueFromAmount(2099999999999999LL), false), "20999999.99999999");
+ BOOST_CHECK(ValueFromAmount(0LL).write() == "0.00000000");
+ BOOST_CHECK(ValueFromAmount(1LL).write() == "0.00000001");
+ BOOST_CHECK(ValueFromAmount(17622195LL).write() == "0.17622195");
+ BOOST_CHECK(ValueFromAmount(50000000LL).write() == "0.50000000");
+ BOOST_CHECK(ValueFromAmount(89898989LL).write() == "0.89898989");
+ BOOST_CHECK(ValueFromAmount(100000000LL).write() == "1.00000000");
+ BOOST_CHECK(ValueFromAmount(2099999999999990LL).write() == "20999999.99999990");
+ BOOST_CHECK(ValueFromAmount(2099999999999999LL).write() == "20999999.99999999");
}
-static Value ValueFromString(const std::string &str)
+static UniValue ValueFromString(const std::string &str)
{
- Value value;
- BOOST_CHECK(read_string(str, value));
+ UniValue value;
+ BOOST_CHECK(value.setNumStr(str));
return value;
}
BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
{
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("-0.00000001")), UniValue);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0")), 0LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000000")), 0LL);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001")), 1LL);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);
@@ -140,6 +144,24 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL);
}
+BOOST_AUTO_TEST_CASE(json_parse_errors)
+{
+ // Valid
+ BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0").get_real(), 1.0);
+ // Valid, with leading or trailing whitespace
+ BOOST_CHECK_EQUAL(ParseNonRFCJSONValue(" 1.0").get_real(), 1.0);
+ BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0 ").get_real(), 1.0);
+ // Invalid, initial garbage
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("[1.0"), std::runtime_error);
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("a1.0"), std::runtime_error);
+ // Invalid, trailing garbage
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0sds"), std::runtime_error);
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0]"), std::runtime_error);
+ // BTC addresses should fail parsing
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"), std::runtime_error);
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"), std::runtime_error);
+}
+
BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr)
{
// Check IPv4 addresses
diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp
index 4d5e92cbd4..a72b656100 100644
--- a/src/test/rpc_wallet_tests.cpp
+++ b/src/test/rpc_wallet_tests.cpp
@@ -14,11 +14,12 @@
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
+#include "univalue/univalue.h"
+
using namespace std;
-using namespace json_spirit;
-extern Array createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL);
-extern Value CallRPC(string args);
+extern UniValue createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL);
+extern UniValue CallRPC(string args);
extern CWallet* pwalletMain;
@@ -35,7 +36,7 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig)
// new, compressed:
const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
- Value v;
+ UniValue v;
CBitcoinAddress address;
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
address.SetString(v.get_str());
@@ -66,13 +67,13 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig)
BOOST_AUTO_TEST_CASE(rpc_wallet)
{
// Test RPC calls for various wallet statistics
- Value r;
+ UniValue r;
LOCK2(cs_main, pwalletMain->cs_wallet);
CPubKey demoPubkey = pwalletMain->GenerateNewKey();
CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
- Value retValue;
+ UniValue retValue;
string strAccount = "walletDemoAccount";
string strPurpose = "receive";
BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
@@ -213,7 +214,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
*********************************/
BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error);
BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
- Array arr = retValue.get_array();
+ UniValue arr = retValue.get_array();
BOOST_CHECK(arr.size() > 0);
BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get());
}
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index c0614cca43..3733425699 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -26,12 +26,10 @@
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
-#include "json/json_spirit_reader_template.h"
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_writer_template.h"
+
+#include "univalue/univalue.h"
using namespace std;
-using namespace json_spirit;
// Uncomment if you want to output updated JSON tests.
// #define UPDATE_JSON_TESTS
@@ -41,15 +39,15 @@ static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
unsigned int ParseScriptFlags(string strFlags);
string FormatScriptFlags(unsigned int flags);
-Array
+UniValue
read_json(const std::string& jsondata)
{
- Value v;
+ UniValue v;
- if (!read_string(jsondata, v) || v.type() != array_type)
+ if (!v.read(jsondata) || !v.isArray())
{
BOOST_ERROR("Parse error.");
- return Array();
+ return UniValue(UniValue::VARR);
}
return v.get_array();
}
@@ -295,10 +293,10 @@ public:
return *this;
}
- Array GetJSON()
+ UniValue GetJSON()
{
DoPush();
- Array array;
+ UniValue array(UniValue::VARR);
array.push_back(FormatScript(spendTx.vin[0].scriptSig));
array.push_back(FormatScript(creditTx.vout[0].scriptPubKey));
array.push_back(FormatScriptFlags(flags));
@@ -582,14 +580,16 @@ BOOST_AUTO_TEST_CASE(script_build)
std::set<std::string> tests_bad;
{
- Array json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
- Array json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
+ UniValue json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
+ UniValue json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
- BOOST_FOREACH(Value& tv, json_good) {
- tests_good.insert(write_string(Value(tv.get_array()), true));
+ for (unsigned int idx = 0; idx < json_good.size(); idx++) {
+ const UniValue& tv = json_good[idx];
+ tests_good.insert(tv.get_array().write());
}
- BOOST_FOREACH(Value& tv, json_bad) {
- tests_bad.insert(write_string(Value(tv.get_array()), true));
+ for (unsigned int idx = 0; idx < json_bad.size(); idx++) {
+ const UniValue& tv = json_bad[idx];
+ tests_bad.insert(tv.get_array().write());
}
}
@@ -598,7 +598,7 @@ BOOST_AUTO_TEST_CASE(script_build)
BOOST_FOREACH(TestBuilder& test, good) {
test.Test(true);
- std::string str = write_string(Value(test.GetJSON()), true);
+ std::string str = test.GetJSON().write();
#ifndef UPDATE_JSON_TESTS
if (tests_good.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment());
@@ -608,7 +608,7 @@ BOOST_AUTO_TEST_CASE(script_build)
}
BOOST_FOREACH(TestBuilder& test, bad) {
test.Test(false);
- std::string str = write_string(Value(test.GetJSON()), true);
+ std::string str = test.GetJSON().write();
#ifndef UPDATE_JSON_TESTS
if (tests_bad.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment());
@@ -634,12 +634,11 @@ BOOST_AUTO_TEST_CASE(script_valid)
// Inner arrays are [ "scriptSig", "scriptPubKey", "flags" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
- Array tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
+ UniValue tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- string strTest = write_string(tv, false);
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ string strTest = test.write();
if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments)
{
if (test.size() != 1) {
@@ -660,13 +659,12 @@ BOOST_AUTO_TEST_CASE(script_valid)
BOOST_AUTO_TEST_CASE(script_invalid)
{
// Scripts that should evaluate as invalid
- Array tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
+ UniValue tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- string strTest = write_string(tv, false);
- if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments)
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ string strTest = test.write();
+ if (test.size() < 3) // Allow size > 2; extra stuff ignored (useful for comments)
{
if (test.size() != 1) {
BOOST_ERROR("Bad test: " << strTest);
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 87be2217c4..a0797d5f3f 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -16,12 +16,10 @@
#include <iostream>
#include <boost/test/unit_test.hpp>
-#include "json/json_spirit_reader_template.h"
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_writer_template.h"
-using namespace json_spirit;
-extern Array read_json(const std::string& jsondata);
+#include "univalue/univalue.h"
+
+extern UniValue read_json(const std::string& jsondata);
// Old script.cpp SignatureHash function
uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
@@ -168,12 +166,11 @@ BOOST_AUTO_TEST_CASE(sighash_test)
// Goal: check that SignatureHash generates correct hash
BOOST_AUTO_TEST_CASE(sighash_from_data)
{
- Array tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
+ UniValue tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
- BOOST_FOREACH(Value& tv, tests)
- {
- Array test = tv.get_array();
- std::string strTest = write_string(tv, false);
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index d12535e438..4cfdec1267 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -20,15 +20,16 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
+#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_writer_template.h"
+
+#include "univalue/univalue.h"
using namespace std;
-using namespace json_spirit;
// In script_tests.cpp
-extern Array read_json(const std::string& jsondata);
+extern UniValue read_json(const std::string& jsondata);
static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
(string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE)
@@ -88,32 +89,31 @@ BOOST_AUTO_TEST_CASE(tx_valid)
// ... where all scripts are stringified scripts.
//
// 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)));
+ UniValue 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();
- string strTest = write_string(tv, false);
- if (test[0].type() == array_type)
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ string strTest = test.write();
+ if (test[0].isArray())
{
- if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type)
+ if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
- Array inputs = test[0].get_array();
+ UniValue inputs = test[0].get_array();
bool fValid = true;
- BOOST_FOREACH(Value& input, inputs)
- {
- if (input.type() != array_type)
+ for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
+ const UniValue& input = inputs[inpIdx];
+ if (!input.isArray())
{
fValid = false;
break;
}
- Array vinput = input.get_array();
+ UniValue vinput = input.get_array();
if (vinput.size() != 3)
{
fValid = false;
@@ -164,32 +164,31 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
// ... where all scripts are stringified scripts.
//
// 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)));
+ UniValue 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();
- string strTest = write_string(tv, false);
- if (test[0].type() == array_type)
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ string strTest = test.write();
+ if (test[0].isArray())
{
- if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type)
+ if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
- Array inputs = test[0].get_array();
+ UniValue inputs = test[0].get_array();
bool fValid = true;
- BOOST_FOREACH(Value& input, inputs)
- {
- if (input.type() != array_type)
+ for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
+ const UniValue& input = inputs[inpIdx];
+ if (!input.isArray())
{
fValid = false;
break;
}
- Array vinput = input.get_array();
+ UniValue vinput = input.get_array();
if (vinput.size() != 3)
{
fValid = false;
diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp
index 8cecfbf651..de84faca23 100644
--- a/src/test/univalue_tests.cpp
+++ b/src/test/univalue_tests.cpp
@@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
double vd = -7.21;
UniValue v7(vd);
- BOOST_CHECK(v7.isNum());
+ BOOST_CHECK(v7.isReal());
BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21");
string vs("yawn");
@@ -63,6 +63,48 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
BOOST_CHECK_EQUAL(v9.getValStr(), "zappa");
}
+BOOST_AUTO_TEST_CASE(univalue_typecheck)
+{
+ UniValue v1;
+ BOOST_CHECK(v1.setNumStr("1"));
+ BOOST_CHECK(v1.isNum());
+ BOOST_CHECK_THROW(v1.get_bool(), runtime_error);
+
+ UniValue v2;
+ BOOST_CHECK(v2.setBool(true));
+ BOOST_CHECK_EQUAL(v2.get_bool(), true);
+ BOOST_CHECK_THROW(v2.get_int(), runtime_error);
+
+ UniValue v3;
+ BOOST_CHECK(v3.setNumStr("32482348723847471234"));
+ BOOST_CHECK_THROW(v3.get_int64(), runtime_error);
+ BOOST_CHECK(v3.setNumStr("1000"));
+ BOOST_CHECK_EQUAL(v3.get_int64(), 1000);
+
+ UniValue v4;
+ BOOST_CHECK(v4.setNumStr("2147483648"));
+ BOOST_CHECK_EQUAL(v4.get_int64(), 2147483648);
+ BOOST_CHECK_THROW(v4.get_int(), runtime_error);
+ BOOST_CHECK(v4.setNumStr("1000"));
+ BOOST_CHECK_EQUAL(v4.get_int(), 1000);
+ BOOST_CHECK_THROW(v4.get_str(), runtime_error);
+ BOOST_CHECK_EQUAL(v4.get_real(), 1000);
+ BOOST_CHECK_THROW(v4.get_array(), runtime_error);
+ BOOST_CHECK_THROW(v4.getKeys(), runtime_error);
+ BOOST_CHECK_THROW(v4.getValues(), runtime_error);
+ BOOST_CHECK_THROW(v4.get_obj(), runtime_error);
+
+ UniValue v5;
+ BOOST_CHECK(v5.read("[true, 10]"));
+ BOOST_CHECK_NO_THROW(v5.get_array());
+ std::vector<UniValue> vals = v5.getValues();
+ BOOST_CHECK_THROW(vals[0].get_int(), runtime_error);
+ BOOST_CHECK_EQUAL(vals[0].get_bool(), true);
+
+ BOOST_CHECK_EQUAL(vals[1].get_int(), 10);
+ BOOST_CHECK_THROW(vals[1].get_bool(), runtime_error);
+}
+
BOOST_AUTO_TEST_CASE(univalue_set)
{
UniValue v(UniValue::VSTR, "foo");
@@ -72,20 +114,20 @@ BOOST_AUTO_TEST_CASE(univalue_set)
BOOST_CHECK(v.setObject());
BOOST_CHECK(v.isObject());
- BOOST_CHECK_EQUAL(v.count(), 0);
+ BOOST_CHECK_EQUAL(v.size(), 0);
BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ);
BOOST_CHECK(v.empty());
BOOST_CHECK(v.setArray());
BOOST_CHECK(v.isArray());
- BOOST_CHECK_EQUAL(v.count(), 0);
+ BOOST_CHECK_EQUAL(v.size(), 0);
BOOST_CHECK(v.setStr("zum"));
BOOST_CHECK(v.isStr());
BOOST_CHECK_EQUAL(v.getValStr(), "zum");
BOOST_CHECK(v.setFloat(-1.01));
- BOOST_CHECK(v.isNum());
+ BOOST_CHECK(v.isReal());
BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
BOOST_CHECK(v.setInt((int)1023));
@@ -145,7 +187,7 @@ BOOST_AUTO_TEST_CASE(univalue_array)
BOOST_CHECK(arr.push_backV(vec));
BOOST_CHECK_EQUAL(arr.empty(), false);
- BOOST_CHECK_EQUAL(arr.count(), 5);
+ BOOST_CHECK_EQUAL(arr.size(), 5);
BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023");
BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy");
@@ -157,7 +199,7 @@ BOOST_AUTO_TEST_CASE(univalue_array)
arr.clear();
BOOST_CHECK(arr.empty());
- BOOST_CHECK_EQUAL(arr.count(), 0);
+ BOOST_CHECK_EQUAL(arr.size(), 0);
}
BOOST_AUTO_TEST_CASE(univalue_object)
@@ -197,7 +239,7 @@ BOOST_AUTO_TEST_CASE(univalue_object)
BOOST_CHECK(obj.pushKVs(obj2));
BOOST_CHECK_EQUAL(obj.empty(), false);
- BOOST_CHECK_EQUAL(obj.count(), 9);
+ BOOST_CHECK_EQUAL(obj.size(), 9);
BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100");
BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John");
@@ -230,7 +272,7 @@ BOOST_AUTO_TEST_CASE(univalue_object)
objTypes["distance"] = UniValue::VNUM;
objTypes["time"] = UniValue::VNUM;
objTypes["calories"] = UniValue::VNUM;
- objTypes["temperature"] = UniValue::VNUM;
+ objTypes["temperature"] = UniValue::VREAL;
objTypes["cat1"] = UniValue::VNUM;
objTypes["cat2"] = UniValue::VNUM;
BOOST_CHECK(obj.checkObject(objTypes));
@@ -240,11 +282,11 @@ BOOST_AUTO_TEST_CASE(univalue_object)
obj.clear();
BOOST_CHECK(obj.empty());
- BOOST_CHECK_EQUAL(obj.count(), 0);
+ BOOST_CHECK_EQUAL(obj.size(), 0);
}
static const char *json1 =
-"[1.1,{\"key1\":\"str\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]";
+"[1.10000000,{\"key1\":\"str\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]";
BOOST_AUTO_TEST_CASE(univalue_readwrite)
{
@@ -255,13 +297,13 @@ BOOST_AUTO_TEST_CASE(univalue_readwrite)
BOOST_CHECK(v.read(strJson1));
BOOST_CHECK(v.isArray());
- BOOST_CHECK_EQUAL(v.count(), 2);
+ BOOST_CHECK_EQUAL(v.size(), 2);
- BOOST_CHECK_EQUAL(v[0].getValStr(), "1.1");
+ BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000");
UniValue obj = v[1];
BOOST_CHECK(obj.isObject());
- BOOST_CHECK_EQUAL(obj.count(), 3);
+ BOOST_CHECK_EQUAL(obj.size(), 3);
BOOST_CHECK(obj["key1"].isStr());
BOOST_CHECK_EQUAL(obj["key1"].getValStr(), "str");
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 3309e2e387..5cb5894251 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -146,29 +146,27 @@ BOOST_AUTO_TEST_CASE(util_GetArg)
BOOST_AUTO_TEST_CASE(util_FormatMoney)
{
- BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00");
- BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789, false), "12345.6789");
- BOOST_CHECK_EQUAL(FormatMoney(COIN, true), "+1.00");
- BOOST_CHECK_EQUAL(FormatMoney(-COIN, false), "-1.00");
- BOOST_CHECK_EQUAL(FormatMoney(-COIN, true), "-1.00");
-
- BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000, false), "100000000.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000, false), "10000000.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000, false), "1000000.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN*100000, false), "100000.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN*10000, false), "10000.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN*1000, false), "1000.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN*100, false), "100.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN*10, false), "10.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN, false), "1.00");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/10, false), "0.10");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/100, false), "0.01");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/1000, false), "0.001");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001");
- BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001");
+ BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
+ BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
+ BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
+
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
}
BOOST_AUTO_TEST_CASE(util_ParseMoney)
@@ -322,9 +320,16 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32)
BOOST_CHECK(ParseInt32("-2147483648", &n) && n == -2147483648);
BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
// Invalid values
+ BOOST_CHECK(!ParseInt32("", &n));
+ BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseInt32("1 ", &n));
BOOST_CHECK(!ParseInt32("1a", &n));
BOOST_CHECK(!ParseInt32("aap", &n));
BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
+ BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseInt32(teststr, &n)); // no embedded NULs
// Overflow and underflow
BOOST_CHECK(!ParseInt32("-2147483649", NULL));
BOOST_CHECK(!ParseInt32("2147483648", NULL));
@@ -332,6 +337,64 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32)
BOOST_CHECK(!ParseInt32("32482348723847471234", NULL));
}
+BOOST_AUTO_TEST_CASE(test_ParseInt64)
+{
+ int64_t n;
+ // Valid values
+ BOOST_CHECK(ParseInt64("1234", NULL));
+ BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
+ BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
+ BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
+ BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
+ BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
+ BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == (int64_t)9223372036854775807);
+ BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == (int64_t)-9223372036854775807-1);
+ BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
+ // Invalid values
+ BOOST_CHECK(!ParseInt64("", &n));
+ BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseInt64("1 ", &n));
+ BOOST_CHECK(!ParseInt64("1a", &n));
+ BOOST_CHECK(!ParseInt64("aap", &n));
+ BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseInt64(teststr, &n)); // no embedded NULs
+ // Overflow and underflow
+ BOOST_CHECK(!ParseInt64("-9223372036854775809", NULL));
+ BOOST_CHECK(!ParseInt64("9223372036854775808", NULL));
+ BOOST_CHECK(!ParseInt64("-32482348723847471234", NULL));
+ BOOST_CHECK(!ParseInt64("32482348723847471234", NULL));
+}
+
+BOOST_AUTO_TEST_CASE(test_ParseDouble)
+{
+ double n;
+ // Valid values
+ BOOST_CHECK(ParseDouble("1234", NULL));
+ BOOST_CHECK(ParseDouble("0", &n) && n == 0.0);
+ BOOST_CHECK(ParseDouble("1234", &n) && n == 1234.0);
+ BOOST_CHECK(ParseDouble("01234", &n) && n == 1234.0); // no octal
+ BOOST_CHECK(ParseDouble("2147483647", &n) && n == 2147483647.0);
+ BOOST_CHECK(ParseDouble("-2147483648", &n) && n == -2147483648.0);
+ BOOST_CHECK(ParseDouble("-1234", &n) && n == -1234.0);
+ BOOST_CHECK(ParseDouble("1e6", &n) && n == 1e6);
+ BOOST_CHECK(ParseDouble("-1e6", &n) && n == -1e6);
+ // Invalid values
+ BOOST_CHECK(!ParseDouble("", &n));
+ BOOST_CHECK(!ParseDouble(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseDouble("1 ", &n));
+ BOOST_CHECK(!ParseDouble("1a", &n));
+ BOOST_CHECK(!ParseDouble("aap", &n));
+ BOOST_CHECK(!ParseDouble("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseDouble(teststr, &n)); // no embedded NULs
+ // Overflow and underflow
+ BOOST_CHECK(!ParseDouble("-1e10000", NULL));
+ BOOST_CHECK(!ParseDouble("1e10000", NULL));
+}
+
BOOST_AUTO_TEST_CASE(test_FormatParagraph)
{
BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
diff --git a/src/univalue/univalue.cpp b/src/univalue/univalue.cpp
index 4e445a542a..6920c44c96 100644
--- a/src/univalue/univalue.cpp
+++ b/src/univalue/univalue.cpp
@@ -4,12 +4,17 @@
#include <stdint.h>
#include <ctype.h>
+#include <iomanip>
#include <sstream>
+#include <stdexcept> // std::runtime_error
+
#include "univalue.h"
+#include "utilstrencodings.h" // ParseXX
+
using namespace std;
-static const UniValue nullValue;
+const UniValue NullUniValue;
void UniValue::clear()
{
@@ -78,9 +83,11 @@ bool UniValue::setFloat(double val)
string s;
ostringstream oss;
- oss << val;
+ oss << std::setprecision(16) << val;
- return setNumStr(oss.str());
+ bool ret = setNumStr(oss.str());
+ typ = VREAL;
+ return ret;
}
bool UniValue::setStr(const string& val_)
@@ -175,11 +182,11 @@ bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t)
const UniValue& UniValue::operator[](const std::string& key) const
{
if (typ != VOBJ)
- return nullValue;
+ return NullUniValue;
int index = findKey(key);
if (index < 0)
- return nullValue;
+ return NullUniValue;
return values[index];
}
@@ -187,9 +194,9 @@ const UniValue& UniValue::operator[](const std::string& key) const
const UniValue& UniValue::operator[](unsigned int index) const
{
if (typ != VOBJ && typ != VARR)
- return nullValue;
+ return NullUniValue;
if (index >= values.size())
- return nullValue;
+ return NullUniValue;
return values[index];
}
@@ -203,9 +210,95 @@ const char *uvTypeName(UniValue::VType t)
case UniValue::VARR: return "array";
case UniValue::VSTR: return "string";
case UniValue::VNUM: return "number";
+ case UniValue::VREAL: return "number";
}
// not reached
return NULL;
}
+const UniValue& find_value( const UniValue& obj, const std::string& name)
+{
+ for (unsigned int i = 0; i < obj.keys.size(); i++)
+ {
+ if( obj.keys[i] == name )
+ {
+ return obj.values[i];
+ }
+ }
+
+ return NullUniValue;
+}
+
+std::vector<std::string> UniValue::getKeys() const
+{
+ if (typ != VOBJ)
+ throw std::runtime_error("JSON value is not an object as expected");
+ return keys;
+}
+
+std::vector<UniValue> UniValue::getValues() const
+{
+ if (typ != VOBJ && typ != VARR)
+ throw std::runtime_error("JSON value is not an object or array as expected");
+ return values;
+}
+
+bool UniValue::get_bool() const
+{
+ if (typ != VBOOL)
+ throw std::runtime_error("JSON value is not a boolean as expected");
+ return getBool();
+}
+
+std::string UniValue::get_str() const
+{
+ if (typ != VSTR)
+ throw std::runtime_error("JSON value is not a string as expected");
+ return getValStr();
+}
+
+int UniValue::get_int() const
+{
+ if (typ != VNUM)
+ throw std::runtime_error("JSON value is not an integer as expected");
+ int32_t retval;
+ if (!ParseInt32(getValStr(), &retval))
+ throw std::runtime_error("JSON integer out of range");
+ return retval;
+}
+
+int64_t UniValue::get_int64() const
+{
+ if (typ != VNUM)
+ throw std::runtime_error("JSON value is not an integer as expected");
+ int64_t retval;
+ if (!ParseInt64(getValStr(), &retval))
+ throw std::runtime_error("JSON integer out of range");
+ return retval;
+}
+
+double UniValue::get_real() const
+{
+ if (typ != VREAL && typ != VNUM)
+ throw std::runtime_error("JSON value is not a number as expected");
+ double retval;
+ if (!ParseDouble(getValStr(), &retval))
+ throw std::runtime_error("JSON double out of range");
+ return retval;
+}
+
+const UniValue& UniValue::get_obj() const
+{
+ if (typ != VOBJ)
+ throw std::runtime_error("JSON value is not an object as expected");
+ return *this;
+}
+
+const UniValue& UniValue::get_array() const
+{
+ if (typ != VARR)
+ throw std::runtime_error("JSON value is not an array as expected");
+ return *this;
+}
+
diff --git a/src/univalue/univalue.h b/src/univalue/univalue.h
index 88d73b8c64..54239741e2 100644
--- a/src/univalue/univalue.h
+++ b/src/univalue/univalue.h
@@ -11,9 +11,12 @@
#include <map>
#include <cassert>
+#include <sstream> // .get_int64()
+#include <utility> // std::pair
+
class UniValue {
public:
- enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
+ enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VREAL, VBOOL, };
UniValue() { typ = VNULL; }
UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
@@ -26,6 +29,9 @@ public:
UniValue(int64_t val_) {
setInt(val_);
}
+ UniValue(bool val_) {
+ setBool(val_);
+ }
UniValue(int val_) {
setInt(val_);
}
@@ -55,10 +61,10 @@ public:
bool setObject();
enum VType getType() const { return typ; }
- std::string getValStr() const { return val; }
+ const std::string& getValStr() const { return val; }
bool empty() const { return (values.size() == 0); }
- size_t count() const { return values.size(); }
+ size_t size() const { return values.size(); }
bool getBool() const { return isTrue(); }
bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes);
@@ -68,10 +74,11 @@ public:
bool isNull() const { return (typ == VNULL); }
bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
- bool isFalse() const { return (!isTrue()); }
+ bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
bool isBool() const { return (typ == VBOOL); }
bool isStr() const { return (typ == VSTR); }
bool isNum() const { return (typ == VNUM); }
+ bool isReal() const { return (typ == VREAL); }
bool isArray() const { return (typ == VARR); }
bool isObject() const { return (typ == VOBJ); }
@@ -130,8 +137,91 @@ private:
int findKey(const std::string& key) const;
void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
+
+public:
+ // Strict type-specific getters, these throw std::runtime_error if the
+ // value is of unexpected type
+ std::vector<std::string> getKeys() const;
+ std::vector<UniValue> getValues() const;
+ bool get_bool() const;
+ std::string get_str() const;
+ int get_int() const;
+ int64_t get_int64() const;
+ double get_real() const;
+ const UniValue& get_obj() const;
+ const UniValue& get_array() const;
+
+ enum VType type() const { return getType(); }
+ bool push_back(std::pair<std::string,UniValue> pear) {
+ return pushKV(pear.first, pear.second);
+ }
+ friend const UniValue& find_value( const UniValue& obj, const std::string& name);
};
+//
+// The following were added for compatibility with json_spirit.
+// Most duplicate other methods, and should be removed.
+//
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, const char *cVal)
+{
+ std::string key(cKey);
+ UniValue uVal(cVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, std::string strVal)
+{
+ std::string key(cKey);
+ UniValue uVal(strVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, uint64_t u64Val)
+{
+ std::string key(cKey);
+ UniValue uVal(u64Val);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, int64_t i64Val)
+{
+ std::string key(cKey);
+ UniValue uVal(i64Val);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, bool iVal)
+{
+ std::string key(cKey);
+ UniValue uVal(iVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, int iVal)
+{
+ std::string key(cKey);
+ UniValue uVal(iVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, double dVal)
+{
+ std::string key(cKey);
+ UniValue uVal(dVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, const UniValue& uVal)
+{
+ std::string key(cKey);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(std::string key, const UniValue& uVal)
+{
+ return std::make_pair(key, uVal);
+}
+
enum jtokentype {
JTOK_ERR = -1,
JTOK_NONE = 0, // eof
@@ -152,4 +242,8 @@ extern enum jtokentype getJsonToken(std::string& tokenVal,
unsigned int& consumed, const char *raw);
extern const char *uvTypeName(UniValue::VType t);
+extern const UniValue NullUniValue;
+
+const UniValue& find_value( const UniValue& obj, const std::string& name);
+
#endif // BITCOIN_UNIVALUE_UNIVALUE_H
diff --git a/src/univalue/univalue_write.cpp b/src/univalue/univalue_write.cpp
index 9a1d364c95..d360c253b0 100644
--- a/src/univalue/univalue_write.cpp
+++ b/src/univalue/univalue_write.cpp
@@ -3,6 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <ctype.h>
+#include <iomanip>
+#include <sstream>
#include <stdio.h>
#include "univalue.h"
#include "univalue_escapes.h"
@@ -59,6 +61,13 @@ string UniValue::write(unsigned int prettyIndent,
case VSTR:
s += "\"" + json_escape(val) + "\"";
break;
+ case VREAL:
+ {
+ std::stringstream ss;
+ ss << std::showpoint << std::fixed << std::setprecision(8) << get_real();
+ s += ss.str();
+ }
+ break;
case VNUM:
s += val;
break;
diff --git a/src/util.cpp b/src/util.cpp
index bfb95c9044..da5821e530 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -208,6 +208,7 @@ bool LogAcceptCategory(const char* category)
// if not debugging everything and not debugging specific category, LogPrint does nothing.
if (setCategories.count(string("")) == 0 &&
+ setCategories.count(string("1")) == 0 &&
setCategories.count(string(category)) == 0)
return false;
}
@@ -701,7 +702,7 @@ boost::filesystem::path GetTempPath() {
#endif
}
-void runCommand(std::string strCommand)
+void runCommand(const std::string& strCommand)
{
int nErr = ::system(strCommand.c_str());
if (nErr)
diff --git a/src/util.h b/src/util.h
index 4cc0faf4d7..6ec81698ea 100644
--- a/src/util.h
+++ b/src/util.h
@@ -126,7 +126,7 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
boost::filesystem::path GetTempPath();
void ShrinkDebugFile();
-void runCommand(std::string strCommand);
+void runCommand(const std::string& strCommand);
inline bool IsSwitchChar(char c)
{
diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp
index 2fbc048878..0f3203432f 100644
--- a/src/utilmoneystr.cpp
+++ b/src/utilmoneystr.cpp
@@ -11,7 +11,7 @@
using namespace std;
-string FormatMoney(const CAmount& n, bool fPlus)
+std::string FormatMoney(const CAmount& n)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
@@ -29,8 +29,6 @@ string FormatMoney(const CAmount& n, bool fPlus)
if (n < 0)
str.insert((unsigned int)0, 1, '-');
- else if (fPlus && n > 0)
- str.insert((unsigned int)0, 1, '+');
return str;
}
diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h
index cd9b04810d..99c3ba8306 100644
--- a/src/utilmoneystr.h
+++ b/src/utilmoneystr.h
@@ -14,7 +14,7 @@
#include "amount.h"
-std::string FormatMoney(const CAmount& n, bool fPlus=false);
+std::string FormatMoney(const CAmount& n);
bool ParseMoney(const std::string& str, CAmount& nRet);
bool ParseMoney(const char* pszIn, CAmount& nRet);
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
index c15bddc6fb..7d1de7d6a8 100644
--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -416,12 +416,25 @@ string DecodeBase32(const string& str)
return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size());
}
+static bool ParsePrechecks(const std::string& str)
+{
+ if (str.empty()) // No empty string allowed
+ return false;
+ if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
+ return false;
+ if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
+ return false;
+ return true;
+}
+
bool ParseInt32(const std::string& str, int32_t *out)
{
+ if (!ParsePrechecks(str))
+ return false;
char *endp = NULL;
errno = 0; // strtol will not set errno if valid
long int n = strtol(str.c_str(), &endp, 10);
- if(out) *out = (int)n;
+ if(out) *out = (int32_t)n;
// Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
// platforms the size of these types may be different.
@@ -430,7 +443,35 @@ bool ParseInt32(const std::string& str, int32_t *out)
n <= std::numeric_limits<int32_t>::max();
}
-std::string FormatParagraph(const std::string in, size_t width, size_t indent)
+bool ParseInt64(const std::string& str, int64_t *out)
+{
+ if (!ParsePrechecks(str))
+ return false;
+ char *endp = NULL;
+ errno = 0; // strtoll will not set errno if valid
+ long long int n = strtoll(str.c_str(), &endp, 10);
+ if(out) *out = (int64_t)n;
+ // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
+ // we still have to check that the returned value is within the range of an *int64_t*.
+ return endp && *endp == 0 && !errno &&
+ n >= std::numeric_limits<int64_t>::min() &&
+ n <= std::numeric_limits<int64_t>::max();
+}
+
+bool ParseDouble(const std::string& str, double *out)
+{
+ if (!ParsePrechecks(str))
+ return false;
+ if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
+ return false;
+ char *endp = NULL;
+ errno = 0; // strtod will not set errno if valid
+ double n = strtod(str.c_str(), &endp);
+ if(out) *out = n;
+ return endp && *endp == 0 && !errno;
+}
+
+std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
{
std::stringstream out;
size_t col = 0;
diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h
index b0edd8b542..58329b51bb 100644
--- a/src/utilstrencodings.h
+++ b/src/utilstrencodings.h
@@ -49,6 +49,20 @@ int atoi(const std::string& str);
*/
bool ParseInt32(const std::string& str, int32_t *out);
+/**
+ * Convert string to signed 64-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 occurred.
+ */
+bool ParseInt64(const std::string& str, int64_t *out);
+
+/**
+ * Convert string to double with strict parse error feedback.
+ * @returns true if the entire string could be parsed as valid double,
+ * false if not the entire string could be parsed or when overflow or underflow occurred.
+ */
+bool ParseDouble(const std::string& str, double *out);
+
template<typename T>
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
{
@@ -74,11 +88,11 @@ 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
* indentation to any added line.
*/
-std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0);
+std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0);
/**
* Timing-attack-resistant comparison.
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index aa9aefb0de..0532da5f37 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -14,7 +14,6 @@ CMainSignals& GetMainSignals()
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
- g_signals.EraseTransaction.connect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1));
g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
@@ -28,7 +27,6 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
- g_signals.EraseTransaction.disconnect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1));
g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
}
@@ -38,7 +36,6 @@ void UnregisterAllValidationInterfaces() {
g_signals.Inventory.disconnect_all_slots();
g_signals.SetBestChain.disconnect_all_slots();
g_signals.UpdatedTransaction.disconnect_all_slots();
- g_signals.EraseTransaction.disconnect_all_slots();
g_signals.SyncTransaction.disconnect_all_slots();
}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index 2a4c7ecceb..a911d1efeb 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -29,7 +29,6 @@ void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL);
class CValidationInterface {
protected:
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {}
- virtual void EraseFromWallet(const uint256 &hash) {}
virtual void SetBestChain(const CBlockLocator &locator) {}
virtual void UpdatedTransaction(const uint256 &hash) {}
virtual void Inventory(const uint256 &hash) {}
@@ -43,8 +42,6 @@ protected:
struct CMainSignals {
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
- /** Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). */
- boost::signals2::signal<void (const uint256 &)> EraseTransaction;
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
/** Notifies listeners of a new active block chain. */
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index b8fb0675ed..5f800474a0 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -19,9 +19,8 @@
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
-#include "json/json_spirit_value.h"
+#include "univalue/univalue.h"
-using namespace json_spirit;
using namespace std;
void EnsureWalletIsUnlocked();
@@ -70,10 +69,10 @@ std::string DecodeDumpString(const std::string &str) {
return ret.str();
}
-Value importprivkey(const Array& params, bool fHelp)
+UniValue importprivkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 3)
throw runtime_error(
@@ -129,7 +128,7 @@ Value importprivkey(const Array& params, bool fHelp)
// Don't throw error in case a key is already there
if (pwalletMain->HaveKey(vchAddress))
- return Value::null;
+ return NullUniValue;
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
@@ -144,13 +143,13 @@ Value importprivkey(const Array& params, bool fHelp)
}
}
- return Value::null;
+ return NullUniValue;
}
-Value importaddress(const Array& params, bool fHelp)
+UniValue importaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 3)
throw runtime_error(
@@ -206,7 +205,7 @@ Value importaddress(const Array& params, bool fHelp)
// Don't throw error in case an address is already there
if (pwalletMain->HaveWatchOnly(script))
- return Value::null;
+ return NullUniValue;
pwalletMain->MarkDirty();
@@ -220,13 +219,13 @@ Value importaddress(const Array& params, bool fHelp)
}
}
- return Value::null;
+ return NullUniValue;
}
-Value importwallet(const Array& params, bool fHelp)
+UniValue importwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -327,13 +326,13 @@ Value importwallet(const Array& params, bool fHelp)
if (!fGood)
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
- return Value::null;
+ return NullUniValue;
}
-Value dumpprivkey(const Array& params, bool fHelp)
+UniValue dumpprivkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -368,10 +367,10 @@ Value dumpprivkey(const Array& params, bool fHelp)
}
-Value dumpwallet(const Array& params, bool fHelp)
+UniValue dumpwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -430,5 +429,5 @@ Value dumpwallet(const Array& params, bool fHelp)
file << "\n";
file << "# End of dump\n";
file.close();
- return Value::null;
+ return NullUniValue;
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index dd5240e3c0..d284fcf15c 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -21,11 +21,9 @@
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_value.h"
+#include "univalue/univalue.h"
using namespace std;
-using namespace json_spirit;
int64_t nWalletUnlockTime;
static CCriticalSection cs_nWalletUnlockTime;
@@ -55,7 +53,7 @@ void EnsureWalletIsUnlocked()
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
}
-void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
+void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
int confirms = wtx.GetDepthInMainChain();
entry.push_back(Pair("confirmations", confirms));
@@ -69,7 +67,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
}
uint256 hash = wtx.GetHash();
entry.push_back(Pair("txid", hash.GetHex()));
- Array conflicts;
+ UniValue conflicts(UniValue::VARR);
BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
conflicts.push_back(conflict.GetHex());
entry.push_back(Pair("walletconflicts", conflicts));
@@ -79,7 +77,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair(item.first, item.second));
}
-string AccountFromValue(const Value& value)
+string AccountFromValue(const UniValue& value)
{
string strAccount = value.get_str();
if (strAccount == "*")
@@ -87,10 +85,10 @@ string AccountFromValue(const Value& value)
return strAccount;
}
-Value getnewaddress(const Array& params, bool fHelp)
+UniValue getnewaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 1)
throw runtime_error(
@@ -166,10 +164,10 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
return CBitcoinAddress(account.vchPubKey.GetID());
}
-Value getaccountaddress(const Array& params, bool fHelp)
+UniValue getaccountaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -191,17 +189,17 @@ Value getaccountaddress(const Array& params, bool fHelp)
// Parse the account first so we don't generate a key if there's an error
string strAccount = AccountFromValue(params[0]);
- Value ret;
+ UniValue ret(UniValue::VSTR);
ret = GetAccountAddress(strAccount).ToString();
return ret;
}
-Value getrawchangeaddress(const Array& params, bool fHelp)
+UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 1)
throw runtime_error(
@@ -233,10 +231,10 @@ Value getrawchangeaddress(const Array& params, bool fHelp)
}
-Value setaccount(const Array& params, bool fHelp)
+UniValue setaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -275,14 +273,14 @@ Value setaccount(const Array& params, bool fHelp)
else
throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
- return Value::null;
+ return NullUniValue;
}
-Value getaccount(const Array& params, bool fHelp)
+UniValue getaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -311,10 +309,10 @@ Value getaccount(const Array& params, bool fHelp)
}
-Value getaddressesbyaccount(const Array& params, bool fHelp)
+UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -337,7 +335,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
string strAccount = AccountFromValue(params[0]);
// Find all addresses that have the given account
- Array ret;
+ UniValue ret(UniValue::VARR);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
@@ -379,10 +377,10 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
}
-Value sendtoaddress(const Array& params, bool fHelp)
+UniValue sendtoaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
@@ -416,12 +414,14 @@ Value sendtoaddress(const Array& params, bool fHelp)
// Amount
CAmount nAmount = AmountFromValue(params[1]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
// Wallet comments
CWalletTx wtx;
- if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
+ if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
wtx.mapValue["comment"] = params[2].get_str();
- if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
+ if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
wtx.mapValue["to"] = params[3].get_str();
bool fSubtractFeeFromAmount = false;
@@ -435,10 +435,10 @@ Value sendtoaddress(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
-Value listaddressgroupings(const Array& params, bool fHelp)
+UniValue listaddressgroupings(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp)
throw runtime_error(
@@ -465,14 +465,14 @@ Value listaddressgroupings(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
- Array jsonGroupings;
+ UniValue jsonGroupings(UniValue::VARR);
map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
{
- Array jsonGrouping;
+ UniValue jsonGrouping(UniValue::VARR);
BOOST_FOREACH(CTxDestination address, grouping)
{
- Array addressInfo;
+ UniValue addressInfo(UniValue::VARR);
addressInfo.push_back(CBitcoinAddress(address).ToString());
addressInfo.push_back(ValueFromAmount(balances[address]));
{
@@ -487,10 +487,10 @@ Value listaddressgroupings(const Array& params, bool fHelp)
return jsonGroupings;
}
-Value signmessage(const Array& params, bool fHelp)
+UniValue signmessage(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 2)
throw runtime_error(
@@ -543,10 +543,10 @@ Value signmessage(const Array& params, bool fHelp)
return EncodeBase64(&vchSig[0], vchSig.size());
}
-Value getreceivedbyaddress(const Array& params, bool fHelp)
+UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -588,7 +588,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -601,10 +601,10 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
}
-Value getreceivedbyaccount(const Array& params, bool fHelp)
+UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -642,7 +642,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -666,7 +666,7 @@ CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
+ if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
continue;
CAmount nReceived, nSent, nFee;
@@ -690,10 +690,10 @@ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminef
}
-Value getbalance(const Array& params, bool fHelp)
+UniValue getbalance(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@@ -765,10 +765,10 @@ Value getbalance(const Array& params, bool fHelp)
return ValueFromAmount(nBalance);
}
-Value getunconfirmedbalance(const Array &params, bool fHelp)
+UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 0)
throw runtime_error(
@@ -781,10 +781,10 @@ Value getunconfirmedbalance(const Array &params, bool fHelp)
}
-Value movecmd(const Array& params, bool fHelp)
+UniValue movecmd(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 3 || params.size() > 5)
throw runtime_error(
@@ -811,6 +811,8 @@ Value movecmd(const Array& params, bool fHelp)
string strFrom = AccountFromValue(params[0]);
string strTo = AccountFromValue(params[1]);
CAmount nAmount = AmountFromValue(params[2]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
if (params.size() > 3)
// unused parameter, used to be nMinDepth, keep type-checking it though
(void)params[3].get_int();
@@ -851,10 +853,10 @@ Value movecmd(const Array& params, bool fHelp)
}
-Value sendfrom(const Array& params, bool fHelp)
+UniValue sendfrom(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 3 || params.size() > 6)
throw runtime_error(
@@ -890,15 +892,17 @@ Value sendfrom(const Array& params, bool fHelp)
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
CAmount nAmount = AmountFromValue(params[2]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
int nMinDepth = 1;
if (params.size() > 3)
nMinDepth = params[3].get_int();
CWalletTx wtx;
wtx.strFromAccount = strAccount;
- if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
+ if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
wtx.mapValue["comment"] = params[4].get_str();
- if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
+ if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
wtx.mapValue["to"] = params[5].get_str();
EnsureWalletIsUnlocked();
@@ -914,10 +918,10 @@ Value sendfrom(const Array& params, bool fHelp)
}
-Value sendmany(const Array& params, bool fHelp)
+UniValue sendmany(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
@@ -958,17 +962,17 @@ Value sendmany(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = AccountFromValue(params[0]);
- Object sendTo = params[1].get_obj();
+ UniValue sendTo = params[1].get_obj();
int nMinDepth = 1;
if (params.size() > 2)
nMinDepth = params[2].get_int();
CWalletTx wtx;
wtx.strFromAccount = strAccount;
- if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
+ if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
wtx.mapValue["comment"] = params[3].get_str();
- Array subtractFeeFromAmount;
+ UniValue subtractFeeFromAmount(UniValue::VARR);
if (params.size() > 4)
subtractFeeFromAmount = params[4].get_array();
@@ -976,24 +980,29 @@ Value sendmany(const Array& params, bool fHelp)
vector<CRecipient> vecSend;
CAmount totalAmount = 0;
- BOOST_FOREACH(const Pair& s, sendTo)
+ vector<string> keys = sendTo.getKeys();
+ BOOST_FOREACH(const string& name_, keys)
{
- CBitcoinAddress address(s.name_);
+ CBitcoinAddress address(name_);
if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
if (setAddress.count(address))
- throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
+ throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
setAddress.insert(address);
CScript scriptPubKey = GetScriptForDestination(address.Get());
- CAmount nAmount = AmountFromValue(s.value_);
+ CAmount nAmount = AmountFromValue(sendTo[name_]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
totalAmount += nAmount;
bool fSubtractFeeFromAmount = false;
- BOOST_FOREACH(const Value& addr, subtractFeeFromAmount)
- if (addr.get_str() == s.name_)
+ for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
+ const UniValue& addr = subtractFeeFromAmount[idx];
+ if (addr.get_str() == name_)
fSubtractFeeFromAmount = true;
+ }
CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
@@ -1021,12 +1030,12 @@ Value sendmany(const Array& params, bool fHelp)
}
// Defined in rpcmisc.cpp
-extern CScript _createmultisig_redeemScript(const Array& params);
+extern CScript _createmultisig_redeemScript(const UniValue& params);
-Value addmultisigaddress(const Array& params, bool fHelp)
+UniValue addmultisigaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 2 || params.size() > 3)
{
@@ -1086,7 +1095,7 @@ struct tallyitem
}
};
-Value ListReceived(const Array& params, bool fByAccounts)
+UniValue ListReceived(const UniValue& params, bool fByAccounts)
{
// Minimum confirmations
int nMinDepth = 1;
@@ -1109,7 +1118,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
int nDepth = wtx.GetDepthInMainChain();
@@ -1136,7 +1145,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
}
// Reply
- Array ret;
+ UniValue ret(UniValue::VARR);
map<string, tallyitem> mapAccountTally;
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
{
@@ -1165,14 +1174,14 @@ Value ListReceived(const Array& params, bool fByAccounts)
}
else
{
- Object obj;
+ UniValue obj(UniValue::VOBJ);
if(fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
obj.push_back(Pair("address", address.ToString()));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
- Array transactions;
+ UniValue transactions(UniValue::VARR);
if (it != mapTally.end())
{
BOOST_FOREACH(const uint256& item, (*it).second.txids)
@@ -1191,7 +1200,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
CAmount nAmount = (*it).second.nAmount;
int nConf = (*it).second.nConf;
- Object obj;
+ UniValue obj(UniValue::VOBJ);
if((*it).second.fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
obj.push_back(Pair("account", (*it).first));
@@ -1204,10 +1213,10 @@ Value ListReceived(const Array& params, bool fByAccounts)
return ret;
}
-Value listreceivedbyaddress(const Array& params, bool fHelp)
+UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@@ -1241,10 +1250,10 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
return ListReceived(params, false);
}
-Value listreceivedbyaccount(const Array& params, bool fHelp)
+UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@@ -1277,14 +1286,14 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
return ListReceived(params, true);
}
-static void MaybePushAddress(Object & entry, const CTxDestination &dest)
+static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
{
CBitcoinAddress addr;
if (addr.Set(dest))
entry.push_back(Pair("address", addr.ToString()));
}
-void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
+void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
{
CAmount nFee;
string strSentAccount;
@@ -1301,7 +1310,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
{
BOOST_FOREACH(const COutputEntry& s, listSent)
{
- Object entry;
+ UniValue entry(UniValue::VOBJ);
if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", strSentAccount));
@@ -1326,7 +1335,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
account = pwalletMain->mapAddressBook[r.destination].name;
if (fAllAccounts || (account == strAccount))
{
- Object entry;
+ UniValue entry(UniValue::VOBJ);
if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", account));
@@ -1354,13 +1363,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
}
}
-void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
+void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
{
bool fAllAccounts = (strAccount == string("*"));
if (fAllAccounts || acentry.strAccount == strAccount)
{
- Object entry;
+ UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("account", acentry.strAccount));
entry.push_back(Pair("category", "move"));
entry.push_back(Pair("time", acentry.nTime));
@@ -1371,10 +1380,10 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar
}
}
-Value listtransactions(const Array& params, bool fHelp)
+UniValue listtransactions(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 4)
throw runtime_error(
@@ -1449,7 +1458,7 @@ Value listtransactions(const Array& params, bool fHelp)
if (nFrom < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
- Array ret;
+ UniValue ret(UniValue::VARR);
std::list<CAccountingEntry> acentries;
CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
@@ -1472,23 +1481,30 @@ Value listtransactions(const Array& params, bool fHelp)
nFrom = ret.size();
if ((nFrom + nCount) > (int)ret.size())
nCount = ret.size() - nFrom;
- Array::iterator first = ret.begin();
+
+ vector<UniValue> arrTmp = ret.getValues();
+
+ vector<UniValue>::iterator first = arrTmp.begin();
std::advance(first, nFrom);
- Array::iterator last = ret.begin();
+ vector<UniValue>::iterator last = arrTmp.begin();
std::advance(last, nFrom+nCount);
- if (last != ret.end()) ret.erase(last, ret.end());
- if (first != ret.begin()) ret.erase(ret.begin(), first);
+ if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
+ if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
+
+ std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
- std::reverse(ret.begin(), ret.end()); // Return oldest to newest
+ ret.clear();
+ ret.setArray();
+ ret.push_backV(arrTmp);
return ret;
}
-Value listaccounts(const Array& params, bool fHelp)
+UniValue listaccounts(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 2)
throw runtime_error(
@@ -1558,17 +1574,17 @@ Value listaccounts(const Array& params, bool fHelp)
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
- Object ret;
+ UniValue ret(UniValue::VOBJ);
BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
}
return ret;
}
-Value listsinceblock(const Array& params, bool fHelp)
+UniValue listsinceblock(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp)
throw runtime_error(
@@ -1636,7 +1652,7 @@ Value listsinceblock(const Array& params, bool fHelp)
int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
- Array transactions;
+ UniValue transactions(UniValue::VARR);
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
{
@@ -1649,17 +1665,17 @@ Value listsinceblock(const Array& params, bool fHelp)
CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
- Object ret;
+ UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("transactions", transactions));
ret.push_back(Pair("lastblock", lastblock.GetHex()));
return ret;
}
-Value gettransaction(const Array& params, bool fHelp)
+UniValue gettransaction(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -1707,7 +1723,7 @@ Value gettransaction(const Array& params, bool fHelp)
if(params[1].get_bool())
filter = filter | ISMINE_WATCH_ONLY;
- Object entry;
+ UniValue entry(UniValue::VOBJ);
if (!pwalletMain->mapWallet.count(hash))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
@@ -1723,7 +1739,7 @@ Value gettransaction(const Array& params, bool fHelp)
WalletTxToJSON(wtx, entry);
- Array details;
+ UniValue details(UniValue::VARR);
ListTransactions(wtx, "*", 0, false, details, filter);
entry.push_back(Pair("details", details));
@@ -1734,10 +1750,10 @@ Value gettransaction(const Array& params, bool fHelp)
}
-Value backupwallet(const Array& params, bool fHelp)
+UniValue backupwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -1756,14 +1772,14 @@ Value backupwallet(const Array& params, bool fHelp)
if (!BackupWallet(*pwalletMain, strDest))
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
- return Value::null;
+ return NullUniValue;
}
-Value keypoolrefill(const Array& params, bool fHelp)
+UniValue keypoolrefill(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 1)
throw runtime_error(
@@ -1793,7 +1809,7 @@ Value keypoolrefill(const Array& params, bool fHelp)
if (pwalletMain->GetKeyPoolSize() < kpSize)
throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
- return Value::null;
+ return NullUniValue;
}
@@ -1804,10 +1820,10 @@ static void LockWallet(CWallet* pWallet)
pWallet->Lock();
}
-Value walletpassphrase(const Array& params, bool fHelp)
+UniValue walletpassphrase(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
throw runtime_error(
@@ -1860,14 +1876,14 @@ Value walletpassphrase(const Array& params, bool fHelp)
nWalletUnlockTime = GetTime() + nSleepTime;
RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
- return Value::null;
+ return NullUniValue;
}
-Value walletpassphrasechange(const Array& params, bool fHelp)
+UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
throw runtime_error(
@@ -1906,14 +1922,14 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
- return Value::null;
+ return NullUniValue;
}
-Value walletlock(const Array& params, bool fHelp)
+UniValue walletlock(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
throw runtime_error(
@@ -1945,14 +1961,14 @@ Value walletlock(const Array& params, bool fHelp)
nWalletUnlockTime = 0;
}
- return Value::null;
+ return NullUniValue;
}
-Value encryptwallet(const Array& params, bool fHelp)
+UniValue encryptwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
throw runtime_error(
@@ -2006,10 +2022,10 @@ Value encryptwallet(const Array& params, bool fHelp)
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
}
-Value lockunspent(const Array& params, bool fHelp)
+UniValue lockunspent(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -2050,9 +2066,9 @@ Value lockunspent(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
if (params.size() == 1)
- RPCTypeCheck(params, boost::assign::list_of(bool_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
else
- RPCTypeCheck(params, boost::assign::list_of(bool_type)(array_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
bool fUnlock = params[0].get_bool();
@@ -2062,14 +2078,14 @@ Value lockunspent(const Array& params, bool fHelp)
return true;
}
- Array outputs = params[1].get_array();
- BOOST_FOREACH(Value& output, outputs)
- {
- if (output.type() != obj_type)
+ UniValue outputs = params[1].get_array();
+ for (unsigned int idx = 0; idx < outputs.size(); idx++) {
+ const UniValue& output = outputs[idx];
+ if (!output.isObject())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
- const Object& o = output.get_obj();
+ const UniValue& o = output.get_obj();
- RPCTypeCheck(o, boost::assign::map_list_of("txid", str_type)("vout", int_type));
+ RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
string txid = find_value(o, "txid").get_str();
if (!IsHex(txid))
@@ -2090,10 +2106,10 @@ Value lockunspent(const Array& params, bool fHelp)
return true;
}
-Value listlockunspent(const Array& params, bool fHelp)
+UniValue listlockunspent(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 0)
throw runtime_error(
@@ -2126,10 +2142,10 @@ Value listlockunspent(const Array& params, bool fHelp)
vector<COutPoint> vOutpts;
pwalletMain->ListLockedCoins(vOutpts);
- Array ret;
+ UniValue ret(UniValue::VARR);
BOOST_FOREACH(COutPoint &outpt, vOutpts) {
- Object o;
+ UniValue o(UniValue::VOBJ);
o.push_back(Pair("txid", outpt.hash.GetHex()));
o.push_back(Pair("vout", (int)outpt.n));
@@ -2139,10 +2155,10 @@ Value listlockunspent(const Array& params, bool fHelp)
return ret;
}
-Value settxfee(const Array& params, bool fHelp)
+UniValue settxfee(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 1)
throw runtime_error(
@@ -2160,18 +2176,16 @@ Value settxfee(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
// Amount
- CAmount nAmount = 0;
- if (params[0].get_real() != 0.0)
- nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
+ CAmount nAmount = AmountFromValue(params[0]);
payTxFee = CFeeRate(nAmount, 1000);
return true;
}
-Value getwalletinfo(const Array& params, bool fHelp)
+UniValue getwalletinfo(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -2195,7 +2209,7 @@ Value getwalletinfo(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
@@ -2208,10 +2222,10 @@ Value getwalletinfo(const Array& params, bool fHelp)
return obj;
}
-Value resendwallettransactions(const Array& params, bool fHelp)
+UniValue resendwallettransactions(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -2225,7 +2239,7 @@ Value resendwallettransactions(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
- Array result;
+ UniValue result(UniValue::VARR);
BOOST_FOREACH(const uint256& txid, txids)
{
result.push_back(txid.ToString());
@@ -2233,10 +2247,10 @@ Value resendwallettransactions(const Array& params, bool fHelp)
return result;
}
-Value listunspent(const Array& params, bool fHelp)
+UniValue listunspent(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
- return Value::null;
+ return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@@ -2274,7 +2288,7 @@ Value listunspent(const Array& params, bool fHelp)
+ HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
);
- RPCTypeCheck(params, boost::assign::list_of(int_type)(int_type)(array_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
int nMinDepth = 1;
if (params.size() > 0)
@@ -2286,8 +2300,9 @@ Value listunspent(const Array& params, bool fHelp)
set<CBitcoinAddress> setAddress;
if (params.size() > 2) {
- Array inputs = params[2].get_array();
- BOOST_FOREACH(Value& input, inputs) {
+ UniValue inputs = params[2].get_array();
+ for (unsigned int idx = 0; idx < inputs.size(); idx++) {
+ const UniValue& input = inputs[idx];
CBitcoinAddress address(input.get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
@@ -2297,7 +2312,7 @@ Value listunspent(const Array& params, bool fHelp)
}
}
- Array results;
+ UniValue results(UniValue::VARR);
vector<COutput> vecOutputs;
assert(pwalletMain != NULL);
LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -2317,7 +2332,7 @@ Value listunspent(const Array& params, bool fHelp)
CAmount nValue = out.tx->vout[out.i].nValue;
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
- Object entry;
+ UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
entry.push_back(Pair("vout", out.i));
CTxDestination address;
@@ -2343,4 +2358,4 @@ Value listunspent(const Array& params, bool fHelp)
}
return results;
-} \ No newline at end of file
+}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index d892c66eda..3f12d88e79 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -776,18 +776,6 @@ void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
}
}
-void CWallet::EraseFromWallet(const uint256 &hash)
-{
- if (!fFileBacked)
- return;
- {
- LOCK(cs_wallet);
- if (mapWallet.erase(hash))
- CWalletDB(strWalletFile).EraseTx(hash);
- }
- return;
-}
-
isminetype CWallet::IsMine(const CTxIn &txin) const
{
@@ -1318,7 +1306,7 @@ CAmount CWalletTx::GetChange() const
bool CWalletTx::IsTrusted() const
{
// Quick answer in most cases
- if (!IsFinalTx(*this))
+ if (!CheckFinalTx(*this))
return false;
int nDepth = GetDepthInMainChain();
if (nDepth >= 1)
@@ -1424,7 +1412,7 @@ CAmount CWallet::GetUnconfirmedBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
+ if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
nTotal += pcoin->GetAvailableCredit();
}
}
@@ -1469,7 +1457,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
+ if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
}
@@ -1504,7 +1492,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
const uint256& wtxid = it->first;
const CWalletTx* pcoin = &(*it).second;
- if (!IsFinalTx(*pcoin))
+ if (!CheckFinalTx(*pcoin))
continue;
if (fOnlyConfirmed && !pcoin->IsTrusted())
@@ -2291,7 +2279,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
{
CWalletTx *pcoin = &walletEntry.second;
- if (!IsFinalTx(*pcoin) || !pcoin->IsTrusted())
+ if (!CheckFinalTx(*pcoin) || !pcoin->IsTrusted())
continue;
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
@@ -2414,7 +2402,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
return ret;
}
-set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
+std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
{
LOCK(cs_wallet);
set<CTxDestination> result;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index b0da92cfd1..9f3f08d117 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -496,7 +496,7 @@ public:
SetNull();
}
- CWallet(std::string strWalletFileIn)
+ CWallet(const std::string& strWalletFileIn)
{
SetNull();
@@ -615,7 +615,6 @@ public:
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
- void EraseFromWallet(const uint256 &hash);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
void ResendWalletTransactions(int64_t nBestBlockTime);
@@ -645,7 +644,7 @@ public:
std::set< std::set<CTxDestination> > GetAddressGroupings();
std::map<CTxDestination, CAmount> GetAddressBalances();
- std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const;
+ std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
isminetype IsMine(const CTxIn& txin) const;
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;