diff --git a/contrib/debian/copyright b/contrib/debian/copyright index fc94e2399..67cb3d67f 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -11,10 +11,6 @@ Comment: The Bitcoin Core developers encompasses the current developers listed o as well as the numerous contributors to the project. The Zcash developers are listed at https://z.cash/team.html. -Files: src/json/* -Copyright: 2007-2009, John W. Wilkinson -License: Expat - Files: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png, src/qt/res/src/*.svg Copyright: Wladimir van der Laan diff --git a/src/Makefile.am b/src/Makefile.am index ce25d1765..2c3274673 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -182,17 +182,6 @@ BITCOIN_CORE_H = \ zmq/zmqpublishnotifier.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 \ @@ -233,7 +222,6 @@ libbitcoin_server_a_SOURCES = \ txdb.cpp \ txmempool.cpp \ validationinterface.cpp \ - $(JSON_H) \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -423,6 +411,7 @@ endif zcash_cli_LDADD = \ $(LIBBITCOIN_CLI) \ + $(LIBBITCOIN_UNIVALUE) \ $(LIBBITCOIN_UTIL) \ $(BOOST_LIBS) \ $(SSL_LIBS) \ diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index a9e5e04dc..d608bfcc1 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -18,7 +18,6 @@ zcash_gtest_SOURCES += \ wallet/gtest/test_wallet_zkeys.cpp endif zcash_gtest_SOURCES += \ - gtest/test_jsonspirit.cpp \ gtest/test_tautology.cpp \ gtest/test_equihash.cpp \ gtest/test_joinsplit.cpp \ diff --git a/src/asyncrpcoperation.cpp b/src/asyncrpcoperation.cpp index 508cd0a51..f32e8d716 100644 --- a/src/asyncrpcoperation.cpp +++ b/src/asyncrpcoperation.cpp @@ -13,7 +13,6 @@ #include using namespace std; -using namespace json_spirit; static boost::uuids::random_generator uuidgen; @@ -109,34 +108,34 @@ void AsyncRPCOperation::main() { */ // Otherwise, if the operation was a success: - Value v("We have a result!"); + UniValue v(UniValue::VSTR, "We have a result!"); set_result(v); set_state(OperationStatus::SUCCESS); } /** - * Return the error of the completed operation as a Value object. - * If there is no error, return null Value. + * Return the error of the completed operation as a UniValue object. + * If there is no error, return null UniValue. */ -Value AsyncRPCOperation::getError() const { +UniValue AsyncRPCOperation::getError() const { if (!isFailed()) { - return Value::null; + return NullUniValue; } std::lock_guard guard(lock_); - Object error; + UniValue error(UniValue::VOBJ); error.push_back(Pair("code", this->error_code_)); error.push_back(Pair("message", this->error_message_)); - return Value(error); + return error; } /** - * Return the result of the completed operation as a Value object. - * If the operation did not succeed, return null Value. + * Return the result of the completed operation as a UniValue object. + * If the operation did not succeed, return null UniValue. */ -Value AsyncRPCOperation::getResult() const { +UniValue AsyncRPCOperation::getResult() const { if (!isSuccess()) { - return Value::null; + return NullUniValue; } std::lock_guard guard(lock_); @@ -145,24 +144,24 @@ Value AsyncRPCOperation::getResult() const { /** - * Returns a status Value object. + * Returns a status UniValue object. * If the operation has failed, it will include an error object. * If the operation has succeeded, it will include the result value. * If the operation was cancelled, there will be no error object or result value. */ -Value AsyncRPCOperation::getStatus() const { +UniValue AsyncRPCOperation::getStatus() const { OperationStatus status = this->getState(); - Object obj; + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("id", this->id_)); obj.push_back(Pair("status", OperationStatusMap[status])); obj.push_back(Pair("creation_time", this->creation_time_)); // TODO: Issue #1354: There may be other useful metadata to return to the user. - Value err = this->getError(); - if (!err.is_null()) { + UniValue err = this->getError(); + if (!err.isNull()) { obj.push_back(Pair("error", err.get_obj())); } - Value result = this->getResult(); - if (!result.is_null()) { + UniValue result = this->getResult(); + if (!result.isNull()) { obj.push_back(Pair("result", result)); // Include execution time for successful operation @@ -170,7 +169,7 @@ Value AsyncRPCOperation::getStatus() const { obj.push_back(Pair("execution_secs", elapsed_seconds.count())); } - return Value(obj); + return obj; } /** diff --git a/src/asyncrpcoperation.h b/src/asyncrpcoperation.h index 526a62ad0..e095e57b1 100644 --- a/src/asyncrpcoperation.h +++ b/src/asyncrpcoperation.h @@ -15,13 +15,9 @@ #include #include -#include "json/json_spirit_value.h" -#include "json/json_spirit_utils.h" -#include "json/json_spirit_reader_template.h" -#include "json/json_spirit_writer_template.h" +#include "univalue/univalue.h" using namespace std; -using namespace json_spirit; /** * AsyncRPCOperation objects are submitted to the AsyncRPCQueue for processing. @@ -67,11 +63,11 @@ public: } // Override this method to add data to the default status object. - virtual Value getStatus() const; + virtual UniValue getStatus() const; - Value getError() const; + UniValue getError() const; - Value getResult() const; + UniValue getResult() const; std::string getStateAsString() const; @@ -114,7 +110,7 @@ protected: // internal state. Currently, all operations are executed in a single-thread // by a single worker. mutable std::mutex lock_; // lock on this when read/writing non-atomics - Value result_; + UniValue result_; int error_code_; std::string error_message_; std::atomic state_; @@ -137,7 +133,7 @@ protected: this->error_message_ = errorMessage; } - void set_result(Value v) { + void set_result(UniValue v) { std::lock_guard guard(lock_); this->result_ = v; } diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 4e15bd197..d589a5a7c 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -12,8 +12,9 @@ #include +#include "univalue/univalue.h" + using namespace std; -using namespace json_spirit; std::string HelpMessageCli() { @@ -96,7 +97,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) { // Connect to localhost bool fUseSSL = GetBoolArg("-rpcssl", false); @@ -152,10 +153,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"); @@ -180,35 +181,34 @@ int CommandLineRPC(int argc, char *argv[]) // Parameters default to strings std::vector 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 ed4e9ff82..b36a01b73 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -347,7 +347,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 (size_t kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) throw runtime_error("privatekey not a string"); CBitcoinSecret vchSecret; @@ -364,7 +364,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 (size_t previdx = 0; previdx < prevtxsObj.size(); previdx++) { UniValue prevOut = prevtxsObj[previdx]; if (!prevOut.isObject()) throw runtime_error("expected prevtxs internal object"); diff --git a/src/gtest/json_test_vectors.cpp b/src/gtest/json_test_vectors.cpp index 737668d9b..94ba5b4c5 100644 --- a/src/gtest/json_test_vectors.cpp +++ b/src/gtest/json_test_vectors.cpp @@ -1,14 +1,14 @@ #include "json_test_vectors.h" -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())) { ADD_FAILURE(); - return Array(); + return UniValue(UniValue::VARR); } return v.get_array(); } diff --git a/src/gtest/json_test_vectors.h b/src/gtest/json_test_vectors.h index 136865bfb..27c8757ec 100644 --- a/src/gtest/json_test_vectors.h +++ b/src/gtest/json_test_vectors.h @@ -5,12 +5,9 @@ #include "serialize.h" #include "streams.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" -using namespace json_spirit; -Array +UniValue read_json(const std::string& jsondata); // #define PRINT_JSON 1 @@ -34,7 +31,7 @@ void expect_deser_same(const T& expected) } template -void expect_test_vector(T& it, const U& expected) +void expect_test_vector(T& v, const U& expected) { expect_deser_same(expected); @@ -45,7 +42,7 @@ void expect_test_vector(T& it, const U& expected) std::cout << "\t\"" ; std::cout << HexStr(ss1.begin(), ss1.end()) << "\",\n"; #else - std::string raw = (it++)->get_str(); + std::string raw = v.get_str(); CDataStream ss2(ParseHex(raw), SER_NETWORK, PROTOCOL_VERSION); ASSERT_TRUE(ss1.size() == ss2.size()); diff --git a/src/gtest/test_jsonspirit.cpp b/src/gtest/test_jsonspirit.cpp deleted file mode 100644 index f93e8d459..000000000 --- a/src/gtest/test_jsonspirit.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include - -#include "json/json_spirit_reader_template.h" - -using namespace json_spirit; - -// This test checks if we have fixed a stack overflow problem with json_spirit. -// It was possible to try and create an unlimited number of nested compound elements. -// Without the fix in json_spirit_reader_template.h, this test will segfault. -TEST(json_spirit_tests, nested_input_segfault) { - std::vector v (100000); - std::fill (v.begin(),v.end(), '['); - std::string s(v.begin(), v.end()); - Value value; - bool b = json_spirit::read_string(s, value); - ASSERT_FALSE(b); -} diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp index cf1d8617a..6bac9ab3c 100644 --- a/src/gtest/test_merkletree.cpp +++ b/src/gtest/test_merkletree.cpp @@ -57,18 +57,15 @@ void expect_ser_test_vector(B& b, const C& c, const A& tree) { template void test_tree( - Array commitment_tests, - Array root_tests, - Array ser_tests, - Array witness_ser_tests, - Array path_tests + UniValue commitment_tests, + UniValue root_tests, + UniValue ser_tests, + UniValue witness_ser_tests, + UniValue path_tests ) { - Array::iterator commitment_iterator = commitment_tests.begin(); - Array::iterator root_iterator = root_tests.begin(); - Array::iterator ser_iterator = ser_tests.begin(); - Array::iterator witness_ser_iterator = witness_ser_tests.begin(); - Array::iterator path_iterator = path_tests.begin(); + size_t witness_ser_i = 0; + size_t path_i = 0; Tree tree; @@ -88,7 +85,7 @@ void test_tree( vector witnesses; for (size_t i = 0; i < 16; i++) { - uint256 test_commitment = uint256S((commitment_iterator++)->get_str()); + uint256 test_commitment = uint256S(commitment_tests[i].get_str()); // Witness here witnesses.push_back(tree.witness()); @@ -103,10 +100,10 @@ void test_tree( ASSERT_TRUE(tree.last() == test_commitment); // Check tree root consistency - expect_test_vector(root_iterator, tree.root()); + expect_test_vector(root_tests[i], tree.root()); // Check serialization of tree - expect_ser_test_vector(ser_iterator, tree, tree); + expect_ser_test_vector(ser_tests[i], tree, tree); bool first = true; // The first witness can never form a path BOOST_FOREACH(Witness& wit, witnesses) @@ -121,7 +118,7 @@ void test_tree( auto path = wit.path(); { - expect_test_vector(path_iterator, path); + expect_test_vector(path_tests[path_i++], path); typedef Fr FieldT; @@ -173,7 +170,7 @@ void test_tree( } // Check witness serialization - expect_ser_test_vector(witness_ser_iterator, wit, tree); + expect_ser_test_vector(witness_ser_tests[witness_ser_i++], wit, tree); ASSERT_TRUE(wit.root() == tree.root()); @@ -192,24 +189,25 @@ void test_tree( } } +#define MAKE_STRING(x) std::string((x), (x)+sizeof(x)) + TEST(merkletree, vectors) { - Array root_tests = read_json(std::string(json_tests::merkle_roots, json_tests::merkle_roots + sizeof(json_tests::merkle_roots))); - Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); - Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); - Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); - Array commitment_tests = read_json(std::string(json_tests::merkle_commitments, json_tests::merkle_commitments + sizeof(json_tests::merkle_commitments))); + UniValue root_tests = read_json(MAKE_STRING(json_tests::merkle_roots)); + UniValue ser_tests = read_json(MAKE_STRING(json_tests::merkle_serialization)); + UniValue witness_ser_tests = read_json(MAKE_STRING(json_tests::merkle_witness_serialization)); + UniValue path_tests = read_json(MAKE_STRING(json_tests::merkle_path)); + UniValue commitment_tests = read_json(MAKE_STRING(json_tests::merkle_commitments)); test_tree(commitment_tests, root_tests, ser_tests, witness_ser_tests, path_tests); } TEST(merkletree, emptyroots) { - Array empty_roots = read_json(std::string(json_tests::merkle_roots_empty, json_tests::merkle_roots_empty + sizeof(json_tests::merkle_roots_empty))); - Array::iterator root_iterator = empty_roots.begin(); + UniValue empty_roots = read_json(MAKE_STRING(json_tests::merkle_roots_empty)); libzcash::EmptyMerkleRoots<64, libzcash::SHA256Compress> emptyroots; for (size_t depth = 0; depth <= 64; depth++) { - expect_test_vector(root_iterator, emptyroots.empty_root(depth)); + expect_test_vector(empty_roots[depth], emptyroots.empty_root(depth)); } // Double check that we're testing (at least) all the empty roots we'll use. diff --git a/src/gtest/test_proofs.cpp b/src/gtest/test_proofs.cpp index 1e8d30bd7..49202f1f6 100644 --- a/src/gtest/test_proofs.cpp +++ b/src/gtest/test_proofs.cpp @@ -629,15 +629,14 @@ TEST(proofs, g2_deserialization) TEST(proofs, g1_test_vectors) { - Array v = read_json(std::string(json_tests::g1_compressed, json_tests::g1_compressed + sizeof(json_tests::g1_compressed))); - Array::iterator v_iterator = v.begin(); + UniValue v = read_json(std::string(json_tests::g1_compressed, json_tests::g1_compressed + sizeof(json_tests::g1_compressed))); curve_G1 e = curve_Fr("34958239045823") * curve_G1::one(); for (size_t i = 0; i < 10000; i++) { e = (curve_Fr("34958239045823") ^ i) * e; auto expected = CompressedG1(e); - expect_test_vector(v_iterator, expected); + expect_test_vector(v[i], expected); ASSERT_TRUE(expected.to_libsnark_g1() == e); } } @@ -646,15 +645,14 @@ TEST(proofs, g1_test_vectors) TEST(proofs, g2_test_vectors) { - Array v = read_json(std::string(json_tests::g2_compressed, json_tests::g2_compressed + sizeof(json_tests::g2_compressed))); - Array::iterator v_iterator = v.begin(); + UniValue v = read_json(std::string(json_tests::g2_compressed, json_tests::g2_compressed + sizeof(json_tests::g2_compressed))); curve_G2 e = curve_Fr("34958239045823") * curve_G2::one(); for (size_t i = 0; i < 10000; i++) { e = (curve_Fr("34958239045823") ^ i) * e; auto expected = CompressedG2(e); - expect_test_vector(v_iterator, expected); + expect_test_vector(v[i], expected); ASSERT_TRUE(expected.to_libsnark_g2() == e); } } diff --git a/src/gtest/test_rpc.cpp b/src/gtest/test_rpc.cpp index dc7a07e0d..baebc7c65 100644 --- a/src/gtest/test_rpc.cpp +++ b/src/gtest/test_rpc.cpp @@ -1,6 +1,5 @@ #include -#include "json/json_spirit_value.h" -#include "json/json_spirit_utils.h" +#include "univalue/univalue.h" #include "chain.h" #include "chainparams.h" @@ -10,7 +9,7 @@ #include "streams.h" #include "utilstrencodings.h" -extern json_spirit::Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); +extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); TEST(rpc, check_blockToJSON_returns_minified_solution) { SelectParams(CBaseChainParams::TESTNET); @@ -24,6 +23,6 @@ TEST(rpc, check_blockToJSON_returns_minified_solution) { CBlockIndex index {block}; index.nHeight = 1391; - json_spirit::Object obj = blockToJSON(block, &index); - EXPECT_EQ("009f44ff7505d789b964d6817734b8ce1377d456255994370d06e59ac99bd5791b6ad174a66fd71c70e60cfc7fd88243ffe06f80b1ad181625f210779c745524629448e25348a5fce4f346a1735e60fdf53e144c0157dbc47c700a21a236f1efb7ee75f65b8d9d9e29026cfd09048233175202b211b9a49de4ab46f1cac71b6ea57a686377bd612378746e70c61a659c9cd683269e9c2a5cbc1d19f1149345302bbd0a1e62bf4bab01e9caeea789a1519441a61b146de35a4cc75dbdf01029127e311ad5073e7e96397f47226a7df9df66b2086b70756db013bbaeb068260157014b2602fc7dc71336e1439c887d2742d9730b4e79b08ec7839c3e2a037ae1565d04e05e351bb3531e5ef42cf7b71ca1482a9205245dd41f4db0f71644f8bdb88e845558537c03834c06ac83f336651e54e2edfc12e15ea9b7ea2c074e6155654d44c4d3bd90d9511050e9ad87d170db01448e5be6f45419cd86008978db5e3ceab79890234f992648d69bf1053855387db646ccdee5575c65f81dd0f670b016d9f9a84707d91f77b862f697b8bb08365ba71fbe6bfa47af39155a75ebdcb1e5d69f59c40c9e3a64988c1ec26f7f5159eef5c244d504a9e46125948ecc389c2ec3028ac4ff39ffd66e7743970819272b21e0c2df75b308bc62896873952147e57ed79446db4cdb5a563e76ec4c25899d41128afb9a5f8fc8063621efb7a58b9dd666d30c73e318cdcf3393bfec200e160f500e645f7baac263db99fa4a7c1cb4fea219fc512193102034d379f244c21a81821301b8d47c90247713a3e902c762d7bafa6cdb744eeb6d3b50dd175599d02b6e9f5bbda59366e04862aa765135968426e7ac0116de7351940dc57c0ae451d63f667e39891bc81e09e6c76f6f8a7582f7447c6f5945f717b0e52a7e3dd0c6db4061362123cc53fd8ede4abed4865201dc4d8eb4e5d48baa565183b69a5304a44c0600bb24dcaeee9d95ceebd27c1b0a33e0b46f23797d7d7907300b2bb7d62ef2fc5aa139250c73930c621bb5f41fc235534ee8014dfaddd5245aeb01198420ba7b5c076545329c94d54fa725a8e807579f5f0cc9d98170598023268f5930893620190275e6b3c6f5181e36310a9a475208316911d78f917d724c5946c553b7ec042c563c540114b6b78bd4c6e808ee391a4a9d93e127032983c5b3708037b14aa604cfb034e7c8b0ffdd6936446fe80216178506a87402653a373926eeff66e704daf992a0a9a5c3ad80566c0339be9e5b8e35b3b3226b2f7767e20d992ea6c3d6e322eca37b0c7f7e60060802f5abcc1975841365cadbdc3867063addfc803766ae525375ecddee61f9df9ffcd20343c83ab82b0e91de039c59cb435c8d3159cc338b4901f40c9b5c27043bcf2bd5fa9b685b65c9ba5a1e11a51dd3f773051560341f9ec81d05bf259e2d4b7161f896fbb6812cfc924a32120b7367d5e40439e267adda6a1315bb0d6200ce6a503174c8d2a638ea6fd6b1f486d68db11bdca63c4f4a725d1ab6231ea875484e70b27d293c05803386924f283d4c12bb953474d92b7dd43d2d97193bd96281ebb63fa075d2f9ecd310c70ee1d97b5330bd8fb5791c5943ecf084e5f2c83915acac57519c46b166136068d6f9ec0dd598616e32c591128ce13705a283ca39d5b211409600e07b3713113374d9700207a45394eac5b3b7afc9b1b2bad7d89fd3f35f6b2413ce615ee7869b3569009403b96fdacdb32ef0a7e5229e2b666d51e95bdfb009b892e88bde70621a9b6509f068781392df4bdbc5723bb15071993f0d9a11575af5ff6ef85eaea39bc86805b35d8beee91b779354147f2d85304b8b49d053e7444fdd3deb9d16de331f2552af5b3be7766bb8f3f6a78c62148efb231f2268", json_spirit::find_value(obj, "solution").get_str()); + UniValue obj = blockToJSON(block, &index); + EXPECT_EQ("009f44ff7505d789b964d6817734b8ce1377d456255994370d06e59ac99bd5791b6ad174a66fd71c70e60cfc7fd88243ffe06f80b1ad181625f210779c745524629448e25348a5fce4f346a1735e60fdf53e144c0157dbc47c700a21a236f1efb7ee75f65b8d9d9e29026cfd09048233175202b211b9a49de4ab46f1cac71b6ea57a686377bd612378746e70c61a659c9cd683269e9c2a5cbc1d19f1149345302bbd0a1e62bf4bab01e9caeea789a1519441a61b146de35a4cc75dbdf01029127e311ad5073e7e96397f47226a7df9df66b2086b70756db013bbaeb068260157014b2602fc7dc71336e1439c887d2742d9730b4e79b08ec7839c3e2a037ae1565d04e05e351bb3531e5ef42cf7b71ca1482a9205245dd41f4db0f71644f8bdb88e845558537c03834c06ac83f336651e54e2edfc12e15ea9b7ea2c074e6155654d44c4d3bd90d9511050e9ad87d170db01448e5be6f45419cd86008978db5e3ceab79890234f992648d69bf1053855387db646ccdee5575c65f81dd0f670b016d9f9a84707d91f77b862f697b8bb08365ba71fbe6bfa47af39155a75ebdcb1e5d69f59c40c9e3a64988c1ec26f7f5159eef5c244d504a9e46125948ecc389c2ec3028ac4ff39ffd66e7743970819272b21e0c2df75b308bc62896873952147e57ed79446db4cdb5a563e76ec4c25899d41128afb9a5f8fc8063621efb7a58b9dd666d30c73e318cdcf3393bfec200e160f500e645f7baac263db99fa4a7c1cb4fea219fc512193102034d379f244c21a81821301b8d47c90247713a3e902c762d7bafa6cdb744eeb6d3b50dd175599d02b6e9f5bbda59366e04862aa765135968426e7ac0116de7351940dc57c0ae451d63f667e39891bc81e09e6c76f6f8a7582f7447c6f5945f717b0e52a7e3dd0c6db4061362123cc53fd8ede4abed4865201dc4d8eb4e5d48baa565183b69a5304a44c0600bb24dcaeee9d95ceebd27c1b0a33e0b46f23797d7d7907300b2bb7d62ef2fc5aa139250c73930c621bb5f41fc235534ee8014dfaddd5245aeb01198420ba7b5c076545329c94d54fa725a8e807579f5f0cc9d98170598023268f5930893620190275e6b3c6f5181e36310a9a475208316911d78f917d724c5946c553b7ec042c563c540114b6b78bd4c6e808ee391a4a9d93e127032983c5b3708037b14aa604cfb034e7c8b0ffdd6936446fe80216178506a87402653a373926eeff66e704daf992a0a9a5c3ad80566c0339be9e5b8e35b3b3226b2f7767e20d992ea6c3d6e322eca37b0c7f7e60060802f5abcc1975841365cadbdc3867063addfc803766ae525375ecddee61f9df9ffcd20343c83ab82b0e91de039c59cb435c8d3159cc338b4901f40c9b5c27043bcf2bd5fa9b685b65c9ba5a1e11a51dd3f773051560341f9ec81d05bf259e2d4b7161f896fbb6812cfc924a32120b7367d5e40439e267adda6a1315bb0d6200ce6a503174c8d2a638ea6fd6b1f486d68db11bdca63c4f4a725d1ab6231ea875484e70b27d293c05803386924f283d4c12bb953474d92b7dd43d2d97193bd96281ebb63fa075d2f9ecd310c70ee1d97b5330bd8fb5791c5943ecf084e5f2c83915acac57519c46b166136068d6f9ec0dd598616e32c591128ce13705a283ca39d5b211409600e07b3713113374d9700207a45394eac5b3b7afc9b1b2bad7d89fd3f35f6b2413ce615ee7869b3569009403b96fdacdb32ef0a7e5229e2b666d51e95bdfb009b892e88bde70621a9b6509f068781392df4bdbc5723bb15071993f0d9a11575af5ff6ef85eaea39bc86805b35d8beee91b779354147f2d85304b8b49d053e7444fdd3deb9d16de331f2552af5b3be7766bb8f3f6a78c62148efb231f2268", find_value(obj, "solution").get_str()); } diff --git a/src/json/LICENSE.txt b/src/json/LICENSE.txt deleted file mode 100644 index 797d5363b..000000000 --- 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 ac1879d5b..000000000 --- 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 17208507d..000000000 --- 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 - -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 aa4f63722..000000000 --- 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 96494a978..000000000 --- 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 - -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 33aa0958e..000000000 --- a/src/json/json_spirit_reader_template.h +++ /dev/null @@ -1,618 +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 -#include -#include - -#if BOOST_VERSION >= 103800 - #include - #include - #include - #include - #include - #define spirit_namespace boost::spirit::classic -#else - #include - #include - #include - #include - #include - #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 - { - // ZCASH: Prevent potential stack overflow by setting a limit on the number of nested compound elements - if (stack_.size() > 128) { - throw std::domain_error("too many nested elements"); - } - // ENDZCASH - - 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 ¤t_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::end_p, - spirit_namespace::space_p ); - - if( !info.hit ) - { - 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(); - - bool success = read_range( begin, s.end(), value ); - return success && begin == s.end(); - } - - 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 7e59c9adc..000000000 --- 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 553e3b96a..000000000 --- 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 - -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 44d2f06a0..000000000 --- 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 13cc89210..000000000 --- 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 d24a632cf..000000000 --- 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 52e14068e..000000000 --- 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 - -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 6b4978a1f..000000000 --- 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 -#include -#include - -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/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index bdf2925fe..feb282644 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -16,10 +16,10 @@ #include "rpcclient.h" #include "util.h" -#include "json/json_spirit_value.h" - #include +#include "univalue/univalue.h" + #ifdef ENABLE_WALLET #include #endif @@ -167,21 +167,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(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); Q_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 +191,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 - Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false))); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write())); } } catch (const std::exception& e) diff --git a/src/rest.cpp b/src/rest.cpp index 7c238d506..1fce7dfc9 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -16,8 +16,9 @@ #include #include +#include "univalue/univalue.h" + using namespace std; -using namespace json_spirit; static const int MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once @@ -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; } @@ -265,10 +266,9 @@ static bool rest_chaininfo(AcceptedConnection* conn, 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; } @@ -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; } @@ -492,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 @@ -500,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); @@ -516,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 4e6d42a6b..fef578cc5 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -13,13 +13,12 @@ #include -#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 GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) { @@ -74,9 +73,9 @@ double GetNetworkDifficulty(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 @@ -87,12 +86,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); } @@ -116,7 +115,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( @@ -133,7 +132,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( @@ -150,7 +149,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( @@ -168,7 +167,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( @@ -209,12 +208,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())); @@ -228,7 +227,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)); } @@ -239,7 +244,7 @@ Value getrawmempool(const Array& params, bool fHelp) vector vtxid; mempool.queryHashes(vtxid); - Array a; + UniValue a(UniValue::VARR); BOOST_FOREACH(const uint256& hash, vtxid) a.push_back(hash.ToString()); @@ -247,7 +252,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( @@ -272,7 +277,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( @@ -340,7 +345,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( @@ -364,7 +369,7 @@ Value gettxoutsetinfo(const Array& params, bool fHelp) LOCK(cs_main); - Object ret; + UniValue ret(UniValue::VOBJ); CCoinsStats stats; FlushStateToDisk(); @@ -380,7 +385,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( @@ -420,7 +425,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)); @@ -434,14 +439,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; @@ -451,7 +456,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)); @@ -460,7 +465,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( @@ -489,7 +494,7 @@ Value verifychain(const Array& params, bool fHelp) } /** Implementation of IsSuperMajority with better feedback */ -Object SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) +static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) { int nFound = 0; CBlockIndex* pstart = pindex; @@ -500,7 +505,7 @@ Object SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, pstart = pstart->pprev; } - Object rv; + UniValue rv(UniValue::VOBJ); rv.push_back(Pair("status", nFound >= nRequired)); rv.push_back(Pair("found", nFound)); rv.push_back(Pair("required", nRequired)); @@ -508,9 +513,9 @@ Object SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, return rv; } -Object SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) +static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) { - Object rv; + UniValue rv(UniValue::VOBJ); rv.push_back(Pair("id", name)); rv.push_back(Pair("version", version)); rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); @@ -518,7 +523,7 @@ Object SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, c return rv; } -Value getblockchaininfo(const Array& params, bool fHelp) +UniValue getblockchaininfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -555,7 +560,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)); @@ -571,7 +576,7 @@ Value getblockchaininfo(const Array& params, bool fHelp) const Consensus::Params& consensusParams = Params().GetConsensus(); CBlockIndex* tip = chainActive.Tip(); - Array softforks; + UniValue softforks(UniValue::VARR); softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); @@ -603,7 +608,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( @@ -655,10 +660,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())); @@ -693,7 +698,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( @@ -709,14 +714,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( @@ -751,10 +756,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( @@ -790,5 +795,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 b482a8eb9..f0c6611ae 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -11,8 +11,9 @@ #include #include +#include "univalue/univalue.h" + using namespace std; -using namespace json_spirit; class CRPCConvertParam { @@ -135,25 +136,32 @@ CRPCConvertTable::CRPCConvertTable() static CRPCConvertTable rpcCvtTable; -/** Convert strings to command-specific RPC representation */ -Array RPCConvertValues(const std::string &strMethod, const std::vector &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) { - Array params; + 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 */ +UniValue RPCConvertValues(const std::string &strMethod, const std::vector &strParams) +{ + 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 42fa2d06f..d68b4ed6a 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& strParams); +UniValue RPCConvertValues(const std::string& strMethod, const std::vector& 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 c500db398..8f63b752c 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -28,10 +28,8 @@ #include -#include "json/json_spirit_utils.h" -#include "json/json_spirit_value.h" +#include "univalue/univalue.h" -using namespace json_spirit; using namespace std; /** @@ -76,7 +74,7 @@ int64_t GetNetworkHashPS(int lookup, int height) { return (int64_t)(workDiff.getdouble() / timeDiff); } -Value getlocalsolps(const Array& params, bool fHelp) +UniValue getlocalsolps(const UniValue& params, bool fHelp) { if (fHelp) throw runtime_error( @@ -94,7 +92,7 @@ Value getlocalsolps(const Array& params, bool fHelp) return GetLocalSolPS(); } -Value getnetworksolps(const Array& params, bool fHelp) +UniValue getnetworksolps(const UniValue& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( @@ -116,7 +114,7 @@ Value getnetworksolps(const Array& params, bool fHelp) return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); } -Value getnetworkhashps(const Array& params, bool fHelp) +UniValue getnetworkhashps(const UniValue& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( @@ -140,7 +138,7 @@ Value getnetworkhashps(const Array& params, bool fHelp) } #ifdef ENABLE_MINING -Value getgenerate(const Array& params, bool fHelp) +UniValue getgenerate(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -159,7 +157,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( @@ -202,7 +200,7 @@ Value generate(const Array& params, bool fHelp) nHeightEnd = nHeightStart+nGenerate; } unsigned int nExtraNonce = 0; - Array blockHashes; + UniValue blockHashes(UniValue::VARR); unsigned int n = Params().EquihashN(); unsigned int k = Params().EquihashK(); while (nHeight < nHeightEnd) @@ -268,7 +266,7 @@ endloop: } -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( @@ -322,12 +320,12 @@ Value setgenerate(const Array& params, bool fHelp) GenerateBitcoins(fGenerate, nGenProcLimit); #endif - 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( @@ -356,7 +354,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)); @@ -377,7 +375,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( @@ -409,10 +407,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()) @@ -427,7 +425,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( @@ -503,16 +501,16 @@ Value getblocktemplate(const Array& params, bool fHelp) } std::string strMode = "template"; - Value lpval = Value::null; + UniValue lpval = NullUniValue; // TODO: Re-enable coinbasevalue once a specification has been written bool coinbasetxn = true; 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 */ } @@ -522,8 +520,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; @@ -562,14 +560,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: std::string lpstr = lpval.get_str(); @@ -647,10 +645,10 @@ Value getblocktemplate(const Array& params, bool fHelp) UpdateTime(pblock, Params().GetConsensus(), pindexPrev); pblock->nNonce = uint256(); - static const Array aCaps = boost::assign::list_of("proposal"); + UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); - Value txCoinbase = Value::null; - Array transactions; + UniValue txCoinbase = NullUniValue; + UniValue transactions(UniValue::VARR); map setTxIndex; int i = 0; BOOST_FOREACH (CTransaction& tx, pblock->vtx) @@ -661,13 +659,13 @@ Value getblocktemplate(const Array& params, bool fHelp) if (tx.IsCoinBase() && !coinbasetxn) 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)) @@ -692,12 +690,12 @@ Value getblocktemplate(const Array& params, bool fHelp) } } - 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"); @@ -705,13 +703,13 @@ 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())); result.push_back(Pair("transactions", transactions)); if (coinbasetxn) { - assert(txCoinbase.type() == obj_type); + assert(txCoinbase.isObject()); result.push_back(Pair("coinbasetxn", txCoinbase)); } else { result.push_back(Pair("coinbaseaux", aux)); @@ -749,7 +747,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( @@ -810,7 +808,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( @@ -829,7 +827,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) @@ -842,7 +840,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( @@ -861,7 +859,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) @@ -870,7 +868,7 @@ Value estimatepriority(const Array& params, bool fHelp) return mempool.estimatePriority(nBlocks); } -Value getblocksubsidy(const Array& params, bool fHelp) +UniValue getblocksubsidy(const UniValue& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( @@ -899,7 +897,7 @@ Value getblocksubsidy(const Array& params, bool fHelp) nFoundersReward = nReward/5; nReward -= nFoundersReward; } - Object result; + UniValue result(UniValue::VOBJ); result.push_back(Pair("miner", ValueFromAmount(nReward))); result.push_back(Pair("founders", ValueFromAmount(nFoundersReward))); return result; diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index d5770fc47..ef480034c 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -20,12 +20,10 @@ #include #include -#include "json/json_spirit_utils.h" -#include "json/json_spirit_value.h" +#include "univalue/univalue.h" #include "zcash/Address.hpp" -using namespace json_spirit; using namespace std; /** @@ -41,7 +39,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( @@ -80,7 +78,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 @@ -110,7 +108,7 @@ Value getinfo(const Array& params, bool fHelp) } #ifdef ENABLE_WALLET -class DescribeAddressVisitor : public boost::static_visitor +class DescribeAddressVisitor : public boost::static_visitor { private: isminetype mine; @@ -118,10 +116,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) { @@ -132,8 +130,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; @@ -144,7 +142,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)); @@ -156,7 +154,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( @@ -189,7 +187,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) { @@ -205,8 +203,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,7 +214,7 @@ Value validateaddress(const Array& params, bool fHelp) } -Value z_validateaddress(const Array& params, bool fHelp) +UniValue z_validateaddress(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( @@ -263,7 +261,7 @@ Value z_validateaddress(const Array& params, bool fHelp) // address is invalid, nop here as isValid is false. } - Object ret; + UniValue ret(UniValue::VOBJ); ret.push_back(Pair("isvalid", isValid)); if (isValid) { @@ -281,10 +279,10 @@ Value z_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) @@ -342,7 +340,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) { @@ -378,14 +376,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( @@ -439,7 +437,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( @@ -455,8 +453,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 e3d264a57..e8eca24f8 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -16,12 +16,11 @@ #include -#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& vstats) @@ -75,7 +74,7 @@ static void CopyNodeStats(std::vector& 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 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( @@ -271,12 +270,12 @@ Value getaddednodeinfo(const Array& params, bool fHelp) 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; + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("addednode", strAddNode)); ret.push_back(obj); } @@ -291,10 +290,10 @@ Value getaddednodeinfo(const Array& params, bool fHelp) 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,15 +301,15 @@ Value getaddednodeinfo(const Array& params, bool fHelp) LOCK(cs_vNodes); for (list > >::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) { bool fFound = false; - Object node; + UniValue node(UniValue::VOBJ); node.push_back(Pair("address", addrNode.ToString())); BOOST_FOREACH(CNode* pnode, vNodes) if (pnode->addr == addrNode) @@ -332,7 +331,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 +349,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(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 +377,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 +417,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()))); @@ -428,12 +427,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 19badb473..c0aaf2c29 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -25,10 +25,10 @@ #include #include #include -#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; @@ -256,20 +256,20 @@ int ReadHTTPMessage(std::basic_istream& stream, map #include -#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 @@ -161,10 +159,10 @@ int ReadHTTPStatus(std::basic_istream& stream, int &proto); int ReadHTTPHeaders(std::basic_istream& stream, std::map& mapHeadersRet); int ReadHTTPMessage(std::basic_istream& stream, std::map& 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); /** Get name of RPC authentication cookie file */ boost::filesystem::path GetAuthCookieFile(); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 4b4beb796..a23c1d8ee 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -25,13 +25,12 @@ #include #include -#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 addresses; @@ -49,18 +48,18 @@ 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)); } -Array TxJoinSplitToJSON(const CTransaction& tx) { - Array vjoinsplit; +UniValue TxJoinSplitToJSON(const CTransaction& tx) { + UniValue vjoinsplit(UniValue::VARR); for (unsigned int i = 0; i < tx.vjoinsplit.size(); i++) { const JSDescription& jsdescription = tx.vjoinsplit[i]; - Object joinsplit; + UniValue joinsplit(UniValue::VOBJ); joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old))); joinsplit.push_back(Pair("vpub_new", ValueFromAmount(jsdescription.vpub_new))); @@ -68,7 +67,7 @@ Array TxJoinSplitToJSON(const CTransaction& tx) { joinsplit.push_back(Pair("anchor", jsdescription.anchor.GetHex())); { - Array nullifiers; + UniValue nullifiers(UniValue::VARR); BOOST_FOREACH(const uint256 nf, jsdescription.nullifiers) { nullifiers.push_back(nf.GetHex()); } @@ -76,7 +75,7 @@ Array TxJoinSplitToJSON(const CTransaction& tx) { } { - Array commitments; + UniValue commitments(UniValue::VARR); BOOST_FOREACH(const uint256 commitment, jsdescription.commitments) { commitments.push_back(commitment.GetHex()); } @@ -87,7 +86,7 @@ Array TxJoinSplitToJSON(const CTransaction& tx) { joinsplit.push_back(Pair("randomSeed", jsdescription.randomSeed.GetHex())); { - Array macs; + UniValue macs(UniValue::VARR); BOOST_FOREACH(const uint256 mac, jsdescription.macs) { macs.push_back(mac.GetHex()); } @@ -99,7 +98,7 @@ Array TxJoinSplitToJSON(const CTransaction& tx) { joinsplit.push_back(Pair("proof", HexStr(ssProof.begin(), ssProof.end()))); { - Array ciphertexts; + UniValue ciphertexts(UniValue::VARR); for (const ZCNoteEncryption::Ciphertext ct : jsdescription.ciphertexts) { ciphertexts.push_back(HexStr(ct.begin(), ct.end())); } @@ -111,20 +110,20 @@ Array TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } -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)); @@ -133,20 +132,20 @@ 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); } entry.push_back(Pair("vout", vout)); - Array vjoinsplit = TxJoinSplitToJSON(tx); + UniValue vjoinsplit = TxJoinSplitToJSON(tx); entry.push_back(Pair("vjoinsplit", vjoinsplit)); if (!hashBlock.IsNull()) { @@ -165,7 +164,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( @@ -276,13 +275,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( @@ -306,8 +305,9 @@ Value gettxoutproof(const Array& params, bool fHelp) set setTxids; uint256 oneTxid; - Array txids = params[0].get_array(); - BOOST_FOREACH(Value& txid, txids) { + UniValue txids = params[0].get_array(); + for (size_t 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())); @@ -362,7 +362,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( @@ -379,7 +379,7 @@ Value verifytxoutproof(const Array& params, bool fHelp) CMerkleBlock merkleBlock; ssMB >> merkleBlock; - Array res; + UniValue res(UniValue::VARR); vector vMatch; if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot) @@ -395,7 +395,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( @@ -429,20 +429,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 (size_t 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) @@ -453,17 +454,18 @@ Value createrawtransaction(const Array& params, bool fHelp) } set setAddress; - BOOST_FOREACH(const Pair& s, sendTo) { - CBitcoinAddress address(s.name_); + vector 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); @@ -472,7 +474,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( @@ -551,20 +553,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( @@ -590,9 +592,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 scriptData(ParseHexV(params[0], "argument")); @@ -607,9 +609,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()))); @@ -618,7 +620,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( @@ -683,7 +685,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 txData(ParseHexV(params[0], "argument 1")); CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); @@ -726,10 +728,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 (size_t idx = 0; idx < keys.size(); idx++) { + UniValue k = keys[idx]; CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(k.get_str()); if (!fGood) @@ -746,15 +749,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 (size_t 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"); @@ -782,9 +786,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 rsData(ParseHexV(v, "redeemScript")); CScript redeemScript(rsData.begin(), rsData.end()); tempKeystore.AddCScript(redeemScript); @@ -800,7 +804,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 mapSigHashValues = boost::assign::map_list_of (string("ALL"), int(SIGHASH_ALL)) @@ -820,7 +824,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++) { @@ -848,7 +852,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()) { @@ -858,7 +862,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( @@ -882,7 +886,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 4100a7f7c..6fe41193e 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -30,10 +30,10 @@ #include #include #include -#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; @@ -81,41 +81,41 @@ void RPCServer::OnPostCommand(boost::function slot) g_rpcSignals.PostCommand.connect(boost::bind(slot, _1)); } -void RPCTypeCheck(const Array& params, - const list& typesExpected, +void RPCTypeCheck(const UniValue& params, + const list& typesExpected, bool fAllowNull) { - unsigned int i = 0; - BOOST_FOREACH(Value_type t, typesExpected) + size_t i = 0; + 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& typesExpected, +void RPCTypeCheckObj(const UniValue& o, + const map& 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); } } @@ -126,7 +126,7 @@ 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) @@ -137,15 +137,15 @@ CAmount AmountFromValue(const Value& value) return nAmount; } -Value ValueFromAmount(const CAmount& amount) +UniValue ValueFromAmount(const CAmount& amount) { return (double)amount / (double)COIN; } -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+"')"); @@ -153,20 +153,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 ParseHexV(const Value& v, string strName) +vector 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 ParseHexO(const Object& o, string strKey) +vector ParseHexO(const UniValue& o, string strKey) { return ParseHexV(find_value(o, strKey), strKey); } @@ -198,7 +198,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); @@ -231,7 +231,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( @@ -251,7 +251,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) @@ -437,14 +437,14 @@ bool HTTPAuthorized(map& 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; } @@ -862,76 +862,76 @@ void RPCRunLater(const std::string& name, boost::function 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; - for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++) + UniValue ret(UniValue::VARR); + for (size_t 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, @@ -962,8 +962,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 @@ -976,23 +976,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; @@ -1048,7 +1048,7 @@ void ServiceConnection(AcceptedConnection *conn) } } -json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array ¶ms) const +UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms) const { // Find method const CRPCCommand *pcmd = tableRPC[strMethod]; diff --git a/src/rpcserver.h b/src/rpcserver.h index fd53bf116..607cff1c2 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -16,9 +16,9 @@ #include #include -#include "json/json_spirit_reader_template.h" -#include "json/json_spirit_utils.h" -#include "json/json_spirit_writer_template.h" +#include + +#include "univalue/univalue.h" class AsyncRPCQueue; class CRPCCommand; @@ -77,14 +77,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& 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& typesExpected, bool fAllowNull=false); +void RPCTypeCheck(const UniValue& params, + const std::list& 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& typesExpected, bool fAllowNull=false); /** * Run func nSeconds from now. Uses boost deadline timers. @@ -95,7 +96,7 @@ void RPCRunLater(const std::string& name, boost::function 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 { @@ -121,11 +122,11 @@ public: /** * 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 ¶ms) const; + UniValue execute(const std::string &method, const UniValue ¶ms) const; }; extern const CRPCTable tableRPC; @@ -134,17 +135,17 @@ 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 ParseHexV(const json_spirit::Value& v, std::string strName); -extern std::vector 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 ParseHexV(const UniValue& v, std::string strName); +extern std::vector 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 double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); extern std::string HelpRequiringPassphrase(); @@ -153,119 +154,119 @@ extern std::string HelpExampleRpc(std::string methodname, 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 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 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 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 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 getlocalsolps(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getnetworksolps(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 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 getlocalsolps(const UniValue& params, bool fHelp); +extern UniValue getnetworksolps(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 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 zc_benchmark(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value zc_raw_receive(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value zc_sample_joinsplit(const json_spirit::Array& 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 zc_benchmark(const UniValue& params, bool fHelp); +extern UniValue zc_raw_keygen(const UniValue& params, bool fHelp); +extern UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp); +extern UniValue zc_raw_receive(const UniValue& params, bool fHelp); +extern UniValue zc_sample_joinsplit(const UniValue& 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 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 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 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); -extern json_spirit::Value getblocksubsidy(const json_spirit::Array& params, bool fHelp); +extern UniValue getblocksubsidy(const UniValue& params, bool fHelp); -extern json_spirit::Value z_exportkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp -extern json_spirit::Value z_importkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp -extern json_spirit::Value z_getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_listaddresses(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_exportwallet(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp -extern json_spirit::Value z_importwallet(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp -extern json_spirit::Value z_listreceivedbyaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_getbalance(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_gettotalbalance(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_sendmany(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_getoperationstatus(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_getoperationresult(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_listoperationids(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value z_validateaddress(const json_spirit::Array& params, bool fHelp); // in rpcmisc.cpp +extern UniValue z_exportkey(const UniValue& params, bool fHelp); // in rpcdump.cpp +extern UniValue z_importkey(const UniValue& params, bool fHelp); // in rpcdump.cpp +extern UniValue z_getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_listaddresses(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_exportwallet(const UniValue& params, bool fHelp); // in rpcdump.cpp +extern UniValue z_importwallet(const UniValue& params, bool fHelp); // in rpcdump.cpp +extern UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_getbalance(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_gettotalbalance(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_sendmany(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_getoperationresult(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_listoperationids(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue z_validateaddress(const UniValue& params, bool fHelp); // in rpcmisc.cpp // in rest.cpp diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 9a861f182..ab3841c48 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -27,7 +27,6 @@ #include #include #include -#include "json/json_spirit_reader_template.h" #include "key.h" #include "alertkeys.h" diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index f07dd7a7d..bd754cafe 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -17,23 +17,20 @@ #include #include -#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 (size_t 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 result; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + for (size_t 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 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 (size_t 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 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 result; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + + for (size_t 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 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 result; CBitcoinSecret secret; CBitcoinAddress addr; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + for (size_t 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/rpc_tests.cpp b/src/test/rpc_tests.cpp index 16709dc80..9037d3f16 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -13,22 +13,23 @@ #include #include -using namespace std; -using namespace json_spirit; +#include "univalue/univalue.h" -Array +using namespace std; + +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 vArgs; boost::split(vArgs, args, boost::is_any_of(" \t")); @@ -40,14 +41,14 @@ Value CallRPC(string args) vArgs[i] = ""; } } - 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()); } } @@ -58,7 +59,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); @@ -98,7 +99,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\"," @@ -117,20 +118,20 @@ 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; } @@ -148,20 +149,20 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values) BOOST_AUTO_TEST_CASE(json_parse_errors) { - Value value; // Valid - BOOST_CHECK_EQUAL(read_string(std::string("1.0"), value), true); - // Valid, with trailing whitespace - BOOST_CHECK_EQUAL(read_string(std::string("1.0 "), value), true); + 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_EQUAL(read_string(std::string("[1.0"), value), false); - BOOST_CHECK_EQUAL(read_string(std::string("a1.0"), value), false); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("[1.0"), std::runtime_error); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("a1.0"), std::runtime_error); // Invalid, trailing garbage - BOOST_CHECK_EQUAL(read_string(std::string("1.0sds"), value), false); - BOOST_CHECK_EQUAL(read_string(std::string("1.0]"), value), false); + 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_EQUAL(read_string(std::string("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"), value), false); - BOOST_CHECK_EQUAL(read_string(std::string("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"), value), false); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"), std::runtime_error); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"), std::runtime_error); } BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index d0ee27aea..f3d1ce0ed 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -31,15 +31,16 @@ #include #include -using namespace std; -using namespace json_spirit; +#include "univalue/univalue.h" -extern Array createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); -extern Value CallRPC(string args); +using namespace std; + +extern UniValue createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); +extern UniValue CallRPC(string args); extern CWallet* pwalletMain; -bool find_error(const Object& objError, const std::string& expected) { +bool find_error(const UniValue& objError, const std::string& expected) { return find_value(objError, "message").get_str().find(expected) != string::npos; } @@ -56,7 +57,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()); @@ -87,13 +88,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 = ""; string strPurpose = "receive"; BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ @@ -239,10 +240,10 @@ 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_EQUAL(4, arr.size()); bool notFound = true; - for (auto a : arr) { + for (auto a : arr.getValues()) { notFound &= CBitcoinAddress(a.get_str()).Get() != demoAddress.Get(); } BOOST_CHECK(!notFound); @@ -253,17 +254,17 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_THROW(CallRPC("getblocksubsidy too many args"), runtime_error); BOOST_CHECK_THROW(CallRPC("getblocksubsidy -1"), runtime_error); BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 50000")); - Object obj = retValue.get_obj(); - BOOST_CHECK(find_value(obj, "miner") == 10.0); - BOOST_CHECK(find_value(obj, "founders") == 2.5); + UniValue obj = retValue.get_obj(); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 10.0); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 2.5); BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1000000")); obj = retValue.get_obj(); - BOOST_CHECK(find_value(obj, "miner") == 6.25); - BOOST_CHECK(find_value(obj, "founders") == 0.0); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 6.25); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0); BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2000000")); obj = retValue.get_obj(); - BOOST_CHECK(find_value(obj, "miner") == 3.125); - BOOST_CHECK(find_value(obj, "founders") == 0.0); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 3.125); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0); } BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance) @@ -304,7 +305,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress) LOCK2(cs_main, pwalletMain->cs_wallet); - Value retValue; + UniValue retValue; // Check number of args BOOST_CHECK_THROW(CallRPC("z_validateaddress"), runtime_error); @@ -317,7 +318,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress) // This address is not valid, it belongs to another network BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztaaga95QAPyp1kSQ1hD2kguCpzyMHjxWZqaYDEkzbvo7uYQYAw2S8X4Kx98AvhhofMtQL8PAXKHuZsmhRcanavKRKmdCzk")); - Object resultObj = retValue.get_obj(); + UniValue resultObj = retValue.get_obj(); bool b = find_value(resultObj, "isvalid").get_bool(); BOOST_CHECK_EQUAL(b, false); @@ -484,7 +485,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) { LOCK2(cs_main, pwalletMain->cs_wallet); - Value retValue; + UniValue retValue; int n1 = 1000; // number of times to import/export int n2 = 1000; // number of addresses to create and list @@ -515,12 +516,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // Verify we can list the keys imported BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses")); - Array arr = retValue.get_array(); + UniValue arr = retValue.get_array(); BOOST_CHECK(arr.size() == n1); // Put addresses into a set std::unordered_set myaddrs; - for (Value element : arr) { + for (UniValue element : arr.getValues()) { myaddrs.insert(element.get_str()); } @@ -542,7 +543,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // Create a set from them std::unordered_set listaddrs; - for (Value element : arr) { + for (UniValue element : arr.getValues()) { listaddrs.insert(element.get_str()); } @@ -581,7 +582,7 @@ public: start_execution_clock(); std::this_thread::sleep_for(std::chrono::milliseconds(naptime)); stop_execution_clock(); - set_result(Value("done")); + set_result(UniValue(UniValue::VSTR, "done")); set_state(OperationStatus::SUCCESS); } }; @@ -620,8 +621,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_async_operations) BOOST_CHECK_EQUAL(op1->isReady(), false); BOOST_CHECK_EQUAL(op1->isFailed(), false); BOOST_CHECK_EQUAL(op1->isSuccess(), true); - BOOST_CHECK(op1->getError() == Value::null ); - BOOST_CHECK(op1->getResult().is_null() == false ); + BOOST_CHECK_EQUAL(op1->getError().isNull(), true); + BOOST_CHECK_EQUAL(op1->getResult().isNull(), false); BOOST_CHECK_EQUAL(op1->getStateAsString(), "success"); BOOST_CHECK_NE(op1->getStateAsString(), "executing"); @@ -781,12 +782,12 @@ BOOST_AUTO_TEST_CASE(rpc_z_getoperations) // Check if too many args BOOST_CHECK_THROW(CallRPC("z_listoperationids toomany args"), runtime_error); - Value retValue; + UniValue retValue; BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listoperationids")); BOOST_CHECK(retValue.get_array().size() == 2); BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getoperationstatus")); - Array array = retValue.get_array(); + UniValue array = retValue.get_array(); BOOST_CHECK(array.size() == 2); // idempotent @@ -794,18 +795,18 @@ BOOST_AUTO_TEST_CASE(rpc_z_getoperations) array = retValue.get_array(); BOOST_CHECK(array.size() == 2); - for (Value v : array) { - Object obj = v.get_obj(); - Value id = find_value(obj, "id"); + for (UniValue v : array.getValues()) { + UniValue obj = v.get_obj(); + UniValue id = find_value(obj, "id"); - Value result; + UniValue result; // removes result from internal storage BOOST_CHECK_NO_THROW(result = CallRPC("z_getoperationresult [\"" + id.get_str() + "\"]")); - Array resultArray = result.get_array(); + UniValue resultArray = result.get_array(); BOOST_CHECK(resultArray.size() == 1); - Object resultObj = resultArray.front().get_obj(); - Value resultId = find_value(resultObj, "id"); + UniValue resultObj = resultArray[0].get_obj(); + UniValue resultId = find_value(resultObj, "id"); BOOST_CHECK_EQUAL(id.get_str(), resultId.get_str()); // verify the operation has been removed @@ -884,26 +885,26 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters) // Test constructor of AsyncRPCOperation_sendmany try { std::shared_ptr operation(new AsyncRPCOperation_sendmany("",{}, {}, -1)); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "Minconf cannot be negative")); } try { std::shared_ptr operation(new AsyncRPCOperation_sendmany("",{}, {}, 1)); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "From address parameter missing")); } try { std::shared_ptr operation( new AsyncRPCOperation_sendmany("tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ", {}, {}, 1) ); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "No recipients")); } try { std::vector recipients = { SendManyRecipient("dummy",1.0, "") }; std::shared_ptr operation( new AsyncRPCOperation_sendmany("INVALID", recipients, {}, 1) ); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "payment address is invalid")); } @@ -911,7 +912,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters) try { std::vector recipients = { SendManyRecipient("dummy",1.0, "") }; std::shared_ptr operation( new AsyncRPCOperation_sendmany("zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U", recipients, {}, 1) ); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "payment address is for wrong network type")); } @@ -920,7 +921,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters) try { std::vector recipients = { SendManyRecipient("dummy",1.0, "") }; std::shared_ptr operation( new AsyncRPCOperation_sendmany("ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP", recipients, {}, 1) ); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "no spending key found for zaddr")); } } @@ -933,7 +934,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) LOCK(pwalletMain->cs_wallet); - Value retValue; + UniValue retValue; // add keys manually BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress")); @@ -985,7 +986,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) try { proxy.get_memo_from_hex_string(bigmemo); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "too big")); } @@ -995,7 +996,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) try { proxy.get_memo_from_hex_string(badmemo); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "hexadecimal format")); } @@ -1006,7 +1007,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) std::string oddmemo(v.begin(), v.end()); try { proxy.get_memo_from_hex_string(oddmemo); - } catch (const Object& objError) { + } catch (const UniValue& objError) { BOOST_CHECK( find_error(objError, "hexadecimal format")); } } @@ -1061,7 +1062,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) // Raw joinsplit is a zaddr->zaddr { std::string raw = "020000000000000000000100000000000000001027000000000000183a0d4c46c369078705e39bcfebee59a978dbd210ce8de3efc9555a03fbabfd3cea16693d730c63850d7e48ccde79854c19adcb7e9dcd7b7d18805ee09083f6b16e1860729d2d4a90e2f2acd009cf78b5eb0f4a6ee4bdb64b1262d7ce9eb910c460b02022991e968d0c50ee44908e4ccccbc591d0053bcca154dd6d6fc400a29fa686af4682339832ccea362a62aeb9df0d5aa74f86a1e75ac0f48a8ccc41e0a940643c6c33e1d09223b0a46eaf47a1bb4407cfc12b1dcf83a29c0cef51e45c7876ca5b9e5bae86d92976eb3ef68f29cd29386a8be8451b50f82bf9da10c04651868655194da8f6ed3d241bb5b5ff93a3e2bbe44644544d88bcde5cc35978032ee92699c7a61fcbb395e7583f47e698c4d53ede54f956629400bf510fb5e22d03158cc10bdcaaf29e418ef18eb6480dd9c8b9e2a377809f9f32a556ef872febd0021d4ad013aa9f0b7255e98e408d302abefd33a71180b720271835b487ab309e160b06dfe51932120fb84a7ede16b20c53599a11071592109e10260f265ee60d48c62bfe24074020e9b586ce9e9356e68f2ad1a9538258234afe4b83a209f178f45202270eaeaeecaf2ce3100b2c5a714f75f35777a9ebff5ebf47059d2bbf6f3726190216468f2b152673b766225b093f3a2f827c86d6b48b42117fec1d0ac38dd7af700308dcfb02eba821612b16a2c164c47715b9b0c93900893b1aba2ea03765c94d87022db5be06ab338d1912e0936dfe87586d0a8ee49144a6cd2e306abdcb652faa3e0222739deb23154d778b50de75069a4a2cce1208cd1ced3cb4744c9888ce1c2fcd2e66dc31e62d3aa9e423d7275882525e9981f92e84ac85975b8660739407efbe1e34c2249420fde7e17db3096d5b22e83d051d01f0e6e7690dca7d168db338aadf0897fedac10de310db2b1bff762d322935dddbb60c2efb8b15d231fa17b84630371cb275c209f0c4c7d0c68b150ea5cd514122215e3f7fcfb351d69514788d67c2f3c8922581946e3a04bdf1f07f15696ca76eb95b10698bf1188fd882945c57657515889d042a6fc45d38cbc943540c4f0f6d1c45a1574c81f3e42d1eb8702328b729909adee8a5cfed7c79d54627d1fd389af941d878376f7927b9830ca659bf9ab18c5ca5192d52d02723008728d03701b8ab3e1c4a3109409ec0b13df334c7deec3523eeef4c97b5603e643de3a647b873f4c1b47fbfc6586ba66724f112e51fc93839648005043620aa3ce458e246d77977b19c53d98e3e812de006afc1a79744df236582943631d04cc02941ac4be500e4ed9fb9e3e7cc187b1c4050fad1d9d09d5fd70d5d01d615b439d8c0015d2eb10398bcdbf8c4b2bd559dbe4c288a186aed3f86f608da4d582e120c4a896e015e2241900d1daeccd05db968852677c71d752bec46de9962174b46f980e8cc603654daf8b98a3ee92dac066033954164a89568b70b1780c2ce2410b2f816dbeddb2cd463e0c8f21a52cf6427d9647a6fd4bafa8fb4cd4d47ac057b0160bee86c6b2fb8adce214c2bcdda277512200adf0eaa5d2114a2c077b009836a68ec254bfe56f51d147b9afe2ddd9cb917c0c2de19d81b7b8fd9f4574f51fa1207630dc13976f4d7587c962f761af267de71f3909a576e6bedaf6311633910d291ac292c467cc8331ef577aef7646a5d949322fa0367a49f20597a13def53136ee31610395e3e48d291fd8f58504374031fe9dcfba5e06086ebcf01a9106f6a4d6e16e19e4c5bb893f7da79419c94eca31a384be6fa1747284dee0fc3bbc8b1b860172c10b29c1594bb8c747d7fe05827358ff2160f49050001625ffe2e880bd7fc26cd0ffd89750745379a8e862816e08a5a2008043921ab6a4976064ac18f7ee37b6628bc0127d8d5ebd3548e41d8881a082d86f20b32e33094f15a0e6ea6074b08c6cd28142de94713451640a55985051f5577eb54572699d838cb34a79c8939e981c0c277d06a6e2ce69ccb74f8a691ff08f81d8b99e6a86223d29a2b7c8e7b041aba44ea678ae654277f7e91cbfa79158b989164a3d549d9f4feb0cc43169699c13e321fe3f4b94258c75d198ff9184269cd6986c55409e07528c93f64942c6c283ce3917b4bf4c3be2fe3173c8c38cccb35f1fbda0ca88b35a599c0678cb22aa8eabea8249dbd2e4f849fffe69803d299e435ebcd7df95854003d8eda17a74d98b4be0e62d45d7fe48c06a6f464a14f8e0570077cc631279092802a89823f031eef5e1028a6d6fdbd502869a731ee7d28b4d6c71b419462a30d31442d3ee444ffbcbd16d558c9000c97e949c2b1f9d6f6d8db7b9131ebd963620d3fc8595278d6f8fdf49084325373196d53e64142fa5a23eccd6ef908c4d80b8b3e6cc334b7f7012103a3682e4678e9b518163d262a39a2c1a69bf88514c52b7ccd7cc8dc80e71f7c2ec0701cff982573eb0c2c4daeb47fa0b586f4451c10d1da2e5d182b03dd067a5e971b3a6138ca6667aaf853d2ac03b80a1d5870905f2cfb6c78ec3c3719c02f973d638a0f973424a2b0f2b0023f136d60092fe15fba4bc180b9176bd0ff576e053f1af6939fe9ca256203ffaeb3e569f09774d2a6cbf91873e56651f4d6ff77e0b5374b0a1a201d7e523604e0247644544cc571d48c458a4f96f45580b"; - Object obj; + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", raw)); // we have the spending key for the dummy recipient zaddr1 @@ -1079,9 +1080,9 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same). BOOST_CHECK_NO_THROW( proxy.sign_send_raw_transaction(obj) ); - Value result = operation->getResult(); - BOOST_CHECK(!result.is_null()); - Object resultObj = result.get_obj(); + UniValue result = operation->getResult(); + BOOST_CHECK(!result.isNull()); + UniValue resultObj = result.get_obj(); std::string hex = find_value(resultObj, "hex").get_str(); BOOST_CHECK_EQUAL(hex, raw); } @@ -1149,7 +1150,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) BOOST_AUTO_TEST_CASE(rpc_wallet_encrypted_wallet_zkeys) { LOCK2(cs_main, pwalletMain->cs_wallet); - Value retValue; + UniValue retValue; int n = 100; // wallet should currently be empty @@ -1164,7 +1165,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_encrypted_wallet_zkeys) // Verify we can list the keys imported BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses")); - Array arr = retValue.get_array(); + UniValue arr = retValue.get_array(); BOOST_CHECK(arr.size() == n); // Verify that the wallet encryption RPC is disabled diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index cb028dfbb..dfb4c2f65 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -26,12 +26,10 @@ #include #include -#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 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 (size_t 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 (size_t 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 (size_t 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 (size_t 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 c825a8bad..ce554ee3e 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -17,12 +17,10 @@ #include #include -#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) @@ -205,12 +203,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 (size_t 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 f717a5f3e..983756625 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -23,19 +23,20 @@ #include #include +#include #include #include -#include "json/json_spirit_writer_template.h" + +#include "univalue/univalue.h" #include "zcash/Note.hpp" #include "zcash/Address.hpp" #include "zcash/Proof.hpp" 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 mapFlagNames = boost::assign::map_list_of (string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE) @@ -96,33 +97,32 @@ 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))); auto verifier = libzcash::ProofVerifier::Strict(); 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 (size_t 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 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 (size_t 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; @@ -173,33 +173,32 @@ 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))); auto verifier = libzcash::ProofVerifier::Strict(); 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 (size_t 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 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 (size_t 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 8cecfbf65..de84faca2 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 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 46114c066..2224a119d 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -322,9 +322,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 +339,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 4e445a542..6920c44c9 100644 --- a/src/univalue/univalue.cpp +++ b/src/univalue/univalue.cpp @@ -4,12 +4,17 @@ #include #include +#include #include +#include // 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& 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 UniValue::getKeys() const +{ + if (typ != VOBJ) + throw std::runtime_error("JSON value is not an object as expected"); + return keys; +} + +std::vector 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 88d73b8c6..79018bb78 100644 --- a/src/univalue/univalue.h +++ b/src/univalue/univalue.h @@ -11,9 +11,12 @@ #include #include +#include // .get_int64() +#include // 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_); } @@ -58,7 +64,7 @@ public: 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& 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 getKeys() const; + std::vector 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 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 Pair(const char *cKey, const char *cVal) +{ + std::string key(cKey); + UniValue uVal(cVal); + return std::make_pair(key, uVal); +} + +static inline std::pair Pair(const char *cKey, std::string strVal) +{ + std::string key(cKey); + UniValue uVal(strVal); + return std::make_pair(key, uVal); +} + +static inline std::pair Pair(const char *cKey, uint64_t u64Val) +{ + std::string key(cKey); + UniValue uVal(u64Val); + return std::make_pair(key, uVal); +} + +static inline std::pair Pair(const char *cKey, int64_t i64Val) +{ + std::string key(cKey); + UniValue uVal(i64Val); + return std::make_pair(key, uVal); +} + +static inline std::pair Pair(const char *cKey, bool iVal) +{ + std::string key(cKey); + UniValue uVal(iVal); + return std::make_pair(key, uVal); +} + +static inline std::pair Pair(const char *cKey, int iVal) +{ + std::string key(cKey); + UniValue uVal(iVal); + return std::make_pair(key, uVal); +} + +static inline std::pair Pair(const char *cKey, double dVal) +{ + std::string key(cKey); + UniValue uVal(dVal); + return std::make_pair(key, uVal); +} + +static inline std::pair Pair(const char *cKey, const UniValue& uVal) +{ + std::string key(cKey); + return std::make_pair(key, uVal); +} + +static inline std::pair 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,9 @@ 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 9a1d364c9..d360c253b 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 +#include +#include #include #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/utilstrencodings.cpp b/src/utilstrencodings.cpp index 646536f1e..81f9e2f9d 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -432,12 +432,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. @@ -446,6 +459,34 @@ bool ParseInt32(const std::string& str, int32_t *out) n <= std::numeric_limits::max(); } +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::min() && + n <= std::numeric_limits::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; diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index e08de362b..a6184d8f1 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -50,6 +50,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 std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) { diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 122ed53cb..e18dd4408 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -29,16 +29,16 @@ using namespace libzcash; -int find_output(Object obj, int n) { - Value outputMapValue = find_value(obj, "outputmap"); - if (outputMapValue.type() != array_type) { +int find_output(UniValue obj, int n) { + UniValue outputMapValue = find_value(obj, "outputmap"); + if (!outputMapValue.isArray()) { throw JSONRPCError(RPC_WALLET_ERROR, "Missing outputmap for JoinSplit operation"); } - Array outputMap = outputMapValue.get_array(); + UniValue outputMap = outputMapValue.get_array(); assert(outputMap.size() == ZC_NUM_JS_OUTPUTS); for (size_t i = 0; i < outputMap.size(); i++) { - if (outputMap[i] == n) { + if (outputMap[i].get_int() == n) { return i; } } @@ -52,7 +52,7 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( std::vector zOutputs, int minDepth, CAmount fee, - Value contextInfo) : + UniValue contextInfo) : fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee), contextinfo_(contextInfo) { assert(fee_ >= 0); @@ -94,7 +94,7 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( // Log the context info i.e. the call parameters to z_sendmany if (LogAcceptCategory("zrpcunsafe")) { - LogPrint("zrpcunsafe", "%s: z_sendmany initialized (params=%s)\n", getId(), json_spirit::write_string( contextInfo, false)); + LogPrint("zrpcunsafe", "%s: z_sendmany initialized (params=%s)\n", getId(), contextInfo.write()); } else { LogPrint("zrpc", "%s: z_sendmany initialized\n", getId()); } @@ -114,7 +114,7 @@ void AsyncRPCOperation_sendmany::main() { try { success = main_impl(); - } catch (const Object& objError) { + } catch (const UniValue& objError) { int code = find_value(objError, "code").get_int(); std::string message = find_value(objError, "message").get_str(); set_error_code(code); @@ -307,7 +307,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { ); } - Object obj; + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); sign_send_raw_transaction(obj); return true; @@ -385,7 +385,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { } // Create joinsplits, where each output represents a zaddr recipient. - Object obj; + UniValue obj(UniValue::VOBJ); while (zOutputsDeque.size() > 0) { AsyncJoinSplitInfo info; info.vpub_old = 0; @@ -434,7 +434,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { * SCENARIO #3 * Part 1: Add to the transparent value pool. */ - Object obj; + UniValue obj(UniValue::VOBJ); CAmount jsChange = 0; // this is updated after each joinsplit int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0 bool minersFeeProcessed = false; @@ -757,42 +757,47 @@ bool AsyncRPCOperation_sendmany::main_impl() { * Sign and send a raw transaction. * Raw transaction as hex string should be in object field "rawtxn" */ -void AsyncRPCOperation_sendmany::sign_send_raw_transaction(Object obj) +void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj) { // Sign the raw transaction - Value rawtxnValue = find_value(obj, "rawtxn"); - if (rawtxnValue.is_null()) { + UniValue rawtxnValue = find_value(obj, "rawtxn"); + if (rawtxnValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction"); } std::string rawtxn = rawtxnValue.get_str(); - Value signResultValue = signrawtransaction({Value(rawtxn)}, false); - Object signResultObject = signResultValue.get_obj(); - Value completeValue = find_value(signResultObject, "complete"); + UniValue params = UniValue(UniValue::VARR); + params.push_back(rawtxn); + UniValue signResultValue = signrawtransaction(params, false); + UniValue signResultObject = signResultValue.get_obj(); + UniValue completeValue = find_value(signResultObject, "complete"); bool complete = completeValue.get_bool(); if (!complete) { // TODO: #1366 Maybe get "errors" and print array vErrors into a string throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction"); } - Value hexValue = find_value(signResultObject, "hex"); - if (hexValue.is_null()) { + UniValue hexValue = find_value(signResultObject, "hex"); + if (hexValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); } std::string signedtxn = hexValue.get_str(); // Send the signed transaction if (!testmode) { - Value sendResultValue = sendrawtransaction({Value(signedtxn)}, false); - if (sendResultValue.is_null()) { + params.clear(); + params.setArray(); + params.push_back(signedtxn); + UniValue sendResultValue = sendrawtransaction(params, false); + if (sendResultValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Send raw transaction did not return an error or a txid."); } std::string txid = sendResultValue.get_str(); - Object o; + UniValue o(UniValue::VOBJ); o.push_back(Pair("txid", txid)); - set_result(Value(o)); + set_result(o); } else { // Test mode does not send the transaction to the network. @@ -800,11 +805,11 @@ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(Object obj) CTransaction tx; stream >> tx; - Object o; + UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); o.push_back(Pair("txid", tx.GetHash().ToString())); o.push_back(Pair("hex", signedtxn)); - set_result(Value(o)); + set_result(o); } // Keep the signed transaction so we can hash to the same txid @@ -891,7 +896,7 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { return true; } -Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info) { +UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info) { std::vector> witnesses; uint256 anchor; { @@ -902,7 +907,7 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info) } -Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, std::vector & outPoints) { +UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, std::vector & outPoints) { std::vector> witnesses; uint256 anchor; { @@ -912,7 +917,7 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, return perform_joinsplit(info, witnesses, anchor); } -Object AsyncRPCOperation_sendmany::perform_joinsplit( +UniValue AsyncRPCOperation_sendmany::perform_joinsplit( AsyncJoinSplitInfo & info, std::vector> witnesses, uint256 anchor) @@ -1033,8 +1038,8 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit( encryptedNote2 = HexStr(ss2.begin(), ss2.end()); } - Array arrInputMap; - Array arrOutputMap; + UniValue arrInputMap(UniValue::VARR); + UniValue arrOutputMap(UniValue::VARR); for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) { arrInputMap.push_back(inputMap[i]); } @@ -1042,7 +1047,7 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit( arrOutputMap.push_back(outputMap[i]); } - Object obj; + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("encryptednote1", encryptedNote1)); obj.push_back(Pair("encryptednote2", encryptedNote2)); obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end()))); @@ -1118,15 +1123,15 @@ boost::array AsyncRPCOperation_sendmany::get_memo_f /** * Override getStatus() to append the operation's input parameters to the default status object. */ -Value AsyncRPCOperation_sendmany::getStatus() const { - Value v = AsyncRPCOperation::getStatus(); - if (contextinfo_.is_null()) { +UniValue AsyncRPCOperation_sendmany::getStatus() const { + UniValue v = AsyncRPCOperation::getStatus(); + if (contextinfo_.isNull()) { return v; } - Object obj = v.get_obj(); + UniValue obj = v.get_obj(); obj.push_back(Pair("method", "z_sendmany")); obj.push_back(Pair("params", contextinfo_ )); - return Value(obj); + return obj; } diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index 5108de8c5..e870e6039 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -11,17 +11,17 @@ #include "primitives/transaction.h" #include "zcash/JoinSplit.hpp" #include "zcash/Address.hpp" -#include "json/json_spirit_value.h" #include "wallet.h" #include #include +#include "univalue/univalue.h" + // Default transaction fee if caller does not specify one. #define ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE 10000 using namespace libzcash; -using namespace json_spirit; // A recipient is a tuple of address, amount, memo (optional if zaddr) typedef std::tuple SendManyRecipient; @@ -50,7 +50,7 @@ struct WitnessAnchorData { class AsyncRPCOperation_sendmany : public AsyncRPCOperation { public: - AsyncRPCOperation_sendmany(std::string fromAddress, std::vector tOutputs, std::vector zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, Value contextInfo = Value::null); + AsyncRPCOperation_sendmany(std::string fromAddress, std::vector tOutputs, std::vector zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, UniValue contextInfo = NullUniValue); virtual ~AsyncRPCOperation_sendmany(); // We don't want to be copied or moved around @@ -61,14 +61,14 @@ public: virtual void main(); - virtual Value getStatus() const; + virtual UniValue getStatus() const; bool testmode = false; // Set to true to disable sending txs and generating proofs private: friend class TEST_FRIEND_AsyncRPCOperation_sendmany; // class for unit testing - Value contextinfo_; // optional data to include in return value from getStatus() + UniValue contextinfo_; // optional data to include in return value from getStatus() CAmount fee_; int mindepth_; @@ -100,18 +100,18 @@ private: bool main_impl(); // JoinSplit without any input notes to spend - Object perform_joinsplit(AsyncJoinSplitInfo &); + UniValue perform_joinsplit(AsyncJoinSplitInfo &); // JoinSplit with input notes to spend (JSOutPoints)) - Object perform_joinsplit(AsyncJoinSplitInfo &, std::vector & ); + UniValue perform_joinsplit(AsyncJoinSplitInfo &, std::vector & ); // JoinSplit where you have the witnesses and anchor - Object perform_joinsplit( + UniValue perform_joinsplit( AsyncJoinSplitInfo & info, std::vector> witnesses, uint256 anchor); - void sign_send_raw_transaction(Object obj); // throws exception if there was an error + void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error }; @@ -157,15 +157,15 @@ public: return delegate->main_impl(); } - Object perform_joinsplit(AsyncJoinSplitInfo &info) { + UniValue perform_joinsplit(AsyncJoinSplitInfo &info) { return delegate->perform_joinsplit(info); } - Object perform_joinsplit(AsyncJoinSplitInfo &info, std::vector &v ) { + UniValue perform_joinsplit(AsyncJoinSplitInfo &info, std::vector &v ) { return delegate->perform_joinsplit(info, v); } - Object perform_joinsplit( + UniValue perform_joinsplit( AsyncJoinSplitInfo & info, std::vector> witnesses, uint256 anchor) @@ -173,7 +173,7 @@ public: return delegate->perform_joinsplit(info, witnesses, anchor); } - void sign_send_raw_transaction(Object obj) { + void sign_send_raw_transaction(UniValue obj) { delegate->sign_send_raw_transaction(obj); } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 41f3f670f..7f9c89da2 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -19,16 +19,15 @@ #include #include -#include "json/json_spirit_value.h" +#include "univalue/univalue.h" -using namespace json_spirit; using namespace std; void EnsureWalletIsUnlocked(); bool EnsureWalletIsAvailable(bool avoidException); -Value dumpwallet_impl(const Array& params, bool fHelp, bool fDumpZKeys); -Value importwallet_impl(const Array& params, bool fHelp, bool fImportZKeys); +UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys); +UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys); std::string static EncodeDumpTime(int64_t nTime) { @@ -74,10 +73,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( @@ -130,7 +129,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; @@ -145,13 +144,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( @@ -204,7 +203,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(); @@ -218,13 +217,13 @@ Value importaddress(const Array& params, bool fHelp) } } - return Value::null; + return NullUniValue; } -Value z_importwallet(const Array& params, bool fHelp) +UniValue z_importwallet(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() != 1) throw runtime_error( @@ -244,10 +243,10 @@ Value z_importwallet(const Array& params, bool fHelp) return importwallet_impl(params, fHelp, true); } -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( @@ -267,7 +266,7 @@ Value importwallet(const Array& params, bool fHelp) return importwallet_impl(params, fHelp, false); } -Value importwallet_impl(const Array& params, bool fHelp, bool fImportZKeys) +UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys) { LOCK2(cs_main, pwalletMain->cs_wallet); @@ -378,13 +377,13 @@ Value importwallet_impl(const Array& params, bool fHelp, bool fImportZKeys) 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( @@ -420,10 +419,10 @@ Value dumpprivkey(const Array& params, bool fHelp) -Value z_exportwallet(const Array& params, bool fHelp) +UniValue z_exportwallet(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() != 1) throw runtime_error( @@ -441,10 +440,10 @@ Value z_exportwallet(const Array& params, bool fHelp) return dumpwallet_impl(params, fHelp, true); } -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( @@ -462,7 +461,7 @@ Value dumpwallet(const Array& params, bool fHelp) return dumpwallet_impl(params, fHelp, false); } -Value dumpwallet_impl(const Array& params, bool fHelp, bool fDumpZKeys) +UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) { LOCK2(cs_main, pwalletMain->cs_wallet); @@ -548,10 +547,10 @@ Value dumpwallet_impl(const Array& params, bool fHelp, bool fDumpZKeys) } -Value z_importkey(const Array& params, bool fHelp) +UniValue z_importkey(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( @@ -587,7 +586,7 @@ Value z_importkey(const Array& params, bool fHelp) { // Don't throw error in case a key is already there if (pwalletMain->HaveSpendingKey(addr)) - return Value::null; + return NullUniValue; pwalletMain->MarkDirty(); @@ -605,14 +604,14 @@ Value z_importkey(const Array& params, bool fHelp) } } - return Value::null; + return NullUniValue; } -Value z_exportkey(const Array& params, bool fHelp) +UniValue z_exportkey(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() != 1) throw runtime_error( diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b3ec08463..5e1efe2db 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -22,6 +22,7 @@ #include "utiltime.h" #include "asyncrpcoperation.h" +#include "asyncrpcqueue.h" #include "wallet/asyncrpcoperation_sendmany.h" #include "sodium.h" @@ -30,24 +31,21 @@ #include -#include "json/json_spirit_utils.h" -#include "json/json_spirit_value.h" -#include "asyncrpcqueue.h" +#include "univalue/univalue.h" #include using namespace std; -using namespace json_spirit; using namespace libzcash; -extern Array TxJoinSplitToJSON(const CTransaction& tx); +extern UniValue TxJoinSplitToJSON(const CTransaction& tx); int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; // Private method: -Value z_getoperationstatus_IMPL(const Array&, bool); +UniValue z_getoperationstatus_IMPL(const UniValue&, bool); std::string HelpRequiringPassphrase() { @@ -74,7 +72,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)); @@ -88,7 +86,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)); @@ -100,7 +98,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) entry.push_back(Pair("vjoinsplit", TxJoinSplitToJSON(wtx))); } -string AccountFromValue(const Value& value) +string AccountFromValue(const UniValue& value) { string strAccount = value.get_str(); if (strAccount != "") @@ -108,10 +106,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( @@ -185,10 +183,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( @@ -210,17 +208,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( @@ -252,10 +250,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( @@ -294,14 +292,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( @@ -330,10 +328,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( @@ -356,7 +354,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; @@ -398,10 +396,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( @@ -438,9 +436,9 @@ Value sendtoaddress(const Array& params, bool fHelp) // 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; @@ -454,10 +452,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( @@ -484,14 +482,14 @@ Value listaddressgroupings(const Array& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - Array jsonGroupings; + UniValue jsonGroupings(UniValue::VARR); map balances = pwalletMain->GetAddressBalances(); BOOST_FOREACH(set 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])); { @@ -505,10 +503,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( @@ -561,10 +559,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( @@ -619,10 +617,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( @@ -708,10 +706,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( @@ -780,10 +778,10 @@ Value getbalance(const Array& params, bool fHelp) return ValueFromAmount(nBalance); } -Value getunconfirmedbalance(const Array ¶ms, bool fHelp) +UniValue getunconfirmedbalance(const UniValue ¶ms, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() > 0) throw runtime_error( @@ -796,10 +794,10 @@ Value getunconfirmedbalance(const Array ¶ms, 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( @@ -866,10 +864,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( @@ -911,9 +909,9 @@ Value sendfrom(const Array& params, bool fHelp) 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(); @@ -929,10 +927,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( @@ -973,17 +971,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(); @@ -991,24 +989,27 @@ Value sendmany(const Array& params, bool fHelp) vector vecSend; CAmount totalAmount = 0; - BOOST_FOREACH(const Pair& s, sendTo) + vector 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 Zcash address: ")+s.name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash 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_]); totalAmount += nAmount; bool fSubtractFeeFromAmount = false; - BOOST_FOREACH(const Value& addr, subtractFeeFromAmount) - if (addr.get_str() == s.name_) + for (size_t 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); @@ -1036,12 +1037,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) { @@ -1101,7 +1102,7 @@ struct tallyitem } }; -Value ListReceived(const Array& params, bool fByAccounts) +UniValue ListReceived(const UniValue& params, bool fByAccounts) { // Minimum confirmations int nMinDepth = 1; @@ -1151,7 +1152,7 @@ Value ListReceived(const Array& params, bool fByAccounts) } // Reply - Array ret; + UniValue ret(UniValue::VARR); map mapAccountTally; BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook) { @@ -1180,14 +1181,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::max() ? 0 : nConf))); - Array transactions; + UniValue transactions(UniValue::VARR); if (it != mapTally.end()) { BOOST_FOREACH(const uint256& item, (*it).second.txids) @@ -1206,7 +1207,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)); @@ -1219,10 +1220,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( @@ -1256,10 +1257,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( @@ -1292,14 +1293,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; @@ -1316,7 +1317,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)); @@ -1342,7 +1343,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)); @@ -1371,13 +1372,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)); @@ -1388,10 +1389,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( @@ -1467,7 +1468,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 acentries; CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount); @@ -1490,23 +1491,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 arrTmp = ret.getValues(); + + vector::iterator first = arrTmp.begin(); std::advance(first, nFrom); - Array::iterator last = ret.begin(); + vector::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(ret.begin(), ret.end()); // Return oldest to newest + std::reverse(arrTmp.begin(), arrTmp.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( @@ -1576,17 +1584,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( @@ -1654,7 +1662,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::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++) { @@ -1667,17 +1675,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( @@ -1736,7 +1744,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]; @@ -1752,7 +1760,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)); @@ -1763,10 +1771,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( @@ -1806,10 +1814,10 @@ Value backupwallet(const Array& params, bool fHelp) } -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( @@ -1839,7 +1847,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; } @@ -1850,10 +1858,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( @@ -1908,14 +1916,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( @@ -1954,14 +1962,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( @@ -1993,14 +2001,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; auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-developerencryptwallet", false); @@ -2065,10 +2073,10 @@ Value encryptwallet(const Array& params, bool fHelp) return "wallet encrypted; Zcash 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( @@ -2109,9 +2117,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(); @@ -2121,14 +2129,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 (size_t 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)) @@ -2149,10 +2157,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( @@ -2185,10 +2193,10 @@ Value listlockunspent(const Array& params, bool fHelp) vector 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)); @@ -2198,10 +2206,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( @@ -2227,10 +2235,10 @@ Value settxfee(const Array& params, bool fHelp) 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( @@ -2254,7 +2262,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()))); @@ -2267,10 +2275,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( @@ -2284,7 +2292,7 @@ Value resendwallettransactions(const Array& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); std::vector txids = pwalletMain->ResendWalletTransactionsBefore(GetTime()); - Array result; + UniValue result(UniValue::VARR); BOOST_FOREACH(const uint256& txid, txids) { result.push_back(txid.ToString()); @@ -2292,10 +2300,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( @@ -2333,7 +2341,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) @@ -2345,8 +2353,9 @@ Value listunspent(const Array& params, bool fHelp) set setAddress; if (params.size() > 2) { - Array inputs = params[2].get_array(); - BOOST_FOREACH(Value& input, inputs) { + UniValue inputs = params[2].get_array(); + for (size_t 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 Zcash address: ")+input.get_str()); @@ -2356,7 +2365,7 @@ Value listunspent(const Array& params, bool fHelp) } } - Array results; + UniValue results(UniValue::VARR); vector vecOutputs; assert(pwalletMain != NULL); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -2376,7 +2385,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; @@ -2404,7 +2413,7 @@ Value listunspent(const Array& params, bool fHelp) return results; } -Value zc_sample_joinsplit(const json_spirit::Array& params, bool fHelp) +UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp) { if (fHelp) { throw runtime_error( @@ -2432,10 +2441,10 @@ Value zc_sample_joinsplit(const json_spirit::Array& params, bool fHelp) return HexStr(ss.begin(), ss.end()); } -Value zc_benchmark(const json_spirit::Array& params, bool fHelp) +UniValue zc_benchmark(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) { - return Value::null; + return NullUniValue; } if (fHelp || params.size() < 2) { @@ -2523,9 +2532,9 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp) } } - Array results; + UniValue results(UniValue::VARR); for (auto time : sample_times) { - Object result; + UniValue result(UniValue::VOBJ); result.push_back(Pair("runningtime", time)); results.push_back(result); } @@ -2533,10 +2542,10 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp) return results; } -Value zc_raw_receive(const json_spirit::Array& params, bool fHelp) +UniValue zc_raw_receive(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) { - return Value::null; + return NullUniValue; } if (fHelp || params.size() != 2) { @@ -2554,7 +2563,7 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp) ); } - RPCTypeCheck(params, boost::assign::list_of(str_type)(str_type)); + RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VSTR)); LOCK(cs_main); @@ -2605,7 +2614,7 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp) CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << npt; - Object result; + UniValue result(UniValue::VOBJ); result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value))); result.push_back(Pair("note", HexStr(ss.begin(), ss.end()))); result.push_back(Pair("exists", (bool) witnesses[0])); @@ -2614,10 +2623,10 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp) -Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp) +UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) { - return Value::null; + return NullUniValue; } if (fHelp || params.size() != 5) { @@ -2650,8 +2659,8 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp) if (!DecodeHexTx(tx, params[0].get_str())) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); - Object inputs = params[1].get_obj(); - Object outputs = params[2].get_obj(); + UniValue inputs = params[1].get_obj(); + UniValue outputs = params[2].get_obj(); CAmount vpub_old(0); CAmount vpub_new(0); @@ -2668,9 +2677,8 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp) std::vector keys; std::vector commitments; - BOOST_FOREACH(const Pair& s, inputs) - { - CZCSpendingKey spendingkey(s.value_.get_str()); + for (const string& name_ : inputs.getKeys()) { + CZCSpendingKey spendingkey(inputs[name_].get_str()); SpendingKey k = spendingkey.Get(); keys.push_back(k); @@ -2678,7 +2686,7 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp) NotePlaintext npt; { - CDataStream ssData(ParseHexV(s.name_, "note"), SER_NETWORK, PROTOCOL_VERSION); + CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION); ssData >> npt; } @@ -2711,11 +2719,10 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp) vjsin.push_back(JSInput()); } - BOOST_FOREACH(const Pair& s, outputs) - { - CZCPaymentAddress pubaddr(s.name_); + for (const string& name_ : outputs.getKeys()) { + CZCPaymentAddress pubaddr(name_); PaymentAddress addrTo = pubaddr.Get(); - CAmount nAmount = AmountFromValue(s.value_); + CAmount nAmount = AmountFromValue(outputs[name_]); vjsout.push_back(JSOutput(addrTo, nAmount)); } @@ -2795,17 +2802,17 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp) encryptedNote2 = HexStr(ss2.begin(), ss2.end()); } - Object result; + UniValue result(UniValue::VOBJ); result.push_back(Pair("encryptednote1", encryptedNote1)); result.push_back(Pair("encryptednote2", encryptedNote2)); result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end()))); return result; } -Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp) +UniValue zc_raw_keygen(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) { - return Value::null; + return NullUniValue; } if (fHelp || params.size() != 0) { @@ -2833,7 +2840,7 @@ Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp) CZCSpendingKey spendingkey(k); std::string viewing_hex = HexStr(viewing.begin(), viewing.end()); - Object result; + UniValue result(UniValue::VOBJ); result.push_back(Pair("zcaddress", pubaddr.ToString())); result.push_back(Pair("zcsecretkey", spendingkey.ToString())); result.push_back(Pair("zcviewingkey", viewing_hex)); @@ -2841,10 +2848,10 @@ Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp) } -Value z_getnewaddress(const Array& params, bool fHelp) +UniValue z_getnewaddress(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() > 0) throw runtime_error( @@ -2868,10 +2875,10 @@ Value z_getnewaddress(const Array& params, bool fHelp) } -Value z_listaddresses(const Array& params, bool fHelp) +UniValue z_listaddresses(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() > 1) throw runtime_error( @@ -2890,7 +2897,7 @@ Value z_listaddresses(const Array& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - Array ret; + UniValue ret(UniValue::VARR); std::set addresses; pwalletMain->GetPaymentAddresses(addresses); for (auto addr : addresses ) { @@ -2950,10 +2957,10 @@ CAmount getBalanceZaddr(std::string address, int minDepth = 1) { } -Value z_listreceivedbyaddress(const Array& params, bool fHelp) +UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size()==0 || params.size() >2) throw runtime_error( @@ -2996,11 +3003,11 @@ Value z_listreceivedbyaddress(const Array& params, bool fHelp) } - Array result; + UniValue result(UniValue::VARR); std::vector entries; pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false); for (CNotePlaintextEntry & entry : entries) { - Object obj; + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("txid",entry.jsop.hash.ToString())); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value)))); std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end()); @@ -3011,10 +3018,10 @@ Value z_listreceivedbyaddress(const Array& params, bool fHelp) } -Value z_getbalance(const Array& params, bool fHelp) +UniValue z_getbalance(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size()==0 || params.size() >2) throw runtime_error( @@ -3073,10 +3080,10 @@ Value z_getbalance(const Array& params, bool fHelp) } -Value z_gettotalbalance(const Array& params, bool fHelp) +UniValue z_gettotalbalance(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() > 1) throw runtime_error( @@ -3116,17 +3123,17 @@ Value z_gettotalbalance(const Array& params, bool fHelp) CAmount nBalance = getBalanceTaddr("", nMinDepth); CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth); CAmount nTotalBalance = nBalance + nPrivateBalance; - Object result; + UniValue result(UniValue::VOBJ); result.push_back(Pair("transparent", FormatMoney(nBalance, false))); result.push_back(Pair("private", FormatMoney(nPrivateBalance, false))); result.push_back(Pair("total", FormatMoney(nTotalBalance, false))); return result; } -Value z_getoperationresult(const Array& params, bool fHelp) +UniValue z_getoperationresult(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() > 1) throw runtime_error( @@ -3143,10 +3150,10 @@ Value z_getoperationresult(const Array& params, bool fHelp) return z_getoperationstatus_IMPL(params, true); } -Value z_getoperationstatus(const Array& params, bool fHelp) +UniValue z_getoperationstatus(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() > 1) throw runtime_error( @@ -3163,20 +3170,20 @@ Value z_getoperationstatus(const Array& params, bool fHelp) return z_getoperationstatus_IMPL(params, false); } -Value z_getoperationstatus_IMPL(const Array& params, bool fRemoveFinishedOperations=false) +UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedOperations=false) { LOCK2(cs_main, pwalletMain->cs_wallet); std::set filter; if (params.size()==1) { - Array ids = params[0].get_array(); - for (Value & v : ids) { + UniValue ids = params[0].get_array(); + for (UniValue & v : ids.getValues()) { filter.insert(v.get_str()); } } bool useFilter = (filter.size()>0); - Array ret; + UniValue ret(UniValue::VARR); std::shared_ptr q = getAsyncRPCQueue(); std::vector ids = q->getAllOperationIds(); @@ -3191,7 +3198,7 @@ Value z_getoperationstatus_IMPL(const Array& params, bool fRemoveFinishedOperati // throw JSONRPCError(RPC_INVALID_PARAMETER, "No operation exists for that id."); } - Value status = operation->getStatus(); + UniValue status = operation->getStatus(); if (fRemoveFinishedOperations) { // Caller is only interested in retrieving finished results @@ -3204,13 +3211,19 @@ Value z_getoperationstatus_IMPL(const Array& params, bool fRemoveFinishedOperati } } + std::vector arrTmp = ret.getValues(); + // sort results chronologically by creation_time - std::sort(ret.begin(), ret.end(), [](Value a, Value b) -> bool { + std::sort(arrTmp.begin(), arrTmp.end(), [](UniValue a, UniValue b) -> bool { const int64_t t1 = find_value(a.get_obj(), "creation_time").get_int64(); const int64_t t2 = find_value(b.get_obj(), "creation_time").get_int64(); return t1 < t2; }); + ret.clear(); + ret.setArray(); + ret.push_backV(arrTmp); + return ret; } @@ -3225,10 +3238,10 @@ Value z_getoperationstatus_IMPL(const Array& params, bool fRemoveFinishedOperati #define CTXIN_SPEND_DUST_SIZE 148 #define CTXOUT_REGULAR_SIZE 34 -Value z_sendmany(const Array& params, bool fHelp) +UniValue z_sendmany(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( @@ -3278,7 +3291,7 @@ Value z_sendmany(const Array& params, bool fHelp) } } - Array outputs = params[1].get_array(); + UniValue outputs = params[1].get_array(); if (outputs.size()==0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amounts array is empty."); @@ -3291,15 +3304,13 @@ Value z_sendmany(const Array& params, bool fHelp) std::vector zaddrRecipients; CAmount nTotalOut = 0; - BOOST_FOREACH(Value& output, outputs) - { - if (output.type() != obj_type) + for (const UniValue& o : outputs.getValues()) { + if (!o.isObject()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object"); - const Object& o = output.get_obj(); // sanity check, report error if unknown key-value pairs - for (const Pair& p : o) { - std::string s = p.name_; + for (const string& name_ : o.getKeys()) { + std::string s = name_; if (s != "address" && s != "amount" && s!="memo") throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown key: ")+s); } @@ -3321,9 +3332,9 @@ Value z_sendmany(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+address); setAddress.insert(address); - Value memoValue = find_value(o, "memo"); + UniValue memoValue = find_value(o, "memo"); string memo; - if (!memoValue.is_null()) { + if (!memoValue.isNull()) { memo = memoValue.get_str(); if (!isZaddr) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr. It can only be used with a zaddr."); @@ -3335,7 +3346,7 @@ Value z_sendmany(const Array& params, bool fHelp) } } - Value av = find_value(o, "amount"); + UniValue av = find_value(o, "amount"); CAmount nAmount = AmountFromValue( av ); if (nAmount < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amount must be positive"); @@ -3398,12 +3409,12 @@ Value z_sendmany(const Array& params, bool fHelp) } // Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult. - Object o; + UniValue o(UniValue::VOBJ); o.push_back(Pair("fromaddress", params[0])); o.push_back(Pair("amounts", params[1])); o.push_back(Pair("minconf", nMinDepth)); o.push_back(Pair("fee", std::stod(FormatMoney(nFee)))); - Value contextInfo = Value(o); + UniValue contextInfo = o; // Create operation and add to global queue std::shared_ptr q = getAsyncRPCQueue(); @@ -3414,10 +3425,10 @@ Value z_sendmany(const Array& params, bool fHelp) } -Value z_listoperationids(const Array& params, bool fHelp) +UniValue z_listoperationids(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; + return NullUniValue; if (fHelp || params.size() > 1) throw runtime_error( @@ -3444,7 +3455,7 @@ Value z_listoperationids(const Array& params, bool fHelp) useFilter = true; } - Array ret; + UniValue ret(UniValue::VARR); std::shared_ptr q = getAsyncRPCQueue(); std::vector ids = q->getAllOperationIds(); for (auto id : ids) {