Auto merge of #1990 - str4d:1985-replace-json-spirit-with-univalue, r=str4d

Convert entire source tree from json_spirit to UniValue

This PR cherry-picks bitcoin/bitcoin#6121 and then migrates the Zcash-specific code to UniValue.

Also cherry-picks:
- bitcoin/bitcoin#6241
- bitcoin/bitcoin#6234

Closes #1985.
This commit is contained in:
zkbot 2017-02-10 05:15:53 +00:00
commit e51bd1b556
57 changed files with 1411 additions and 3061 deletions

View File

@ -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

View File

@ -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) \

View File

@ -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 \

View File

@ -13,7 +13,6 @@
#include <chrono>
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<std::mutex> 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<std::mutex> 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;
}
/**

View File

@ -15,13 +15,9 @@
#include <utility>
#include <future>
#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<OperationStatus> state_;
@ -137,7 +133,7 @@ protected:
this->error_message_ = errorMessage;
}
void set_result(Value v) {
void set_result(UniValue v) {
std::lock_guard<std::mutex> guard(lock_);
this->result_ = v;
}

View File

@ -12,8 +12,9 @@
#include <boost/filesystem/operations.hpp>
#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<std::string> strParams(&argv[2], &argv[argc]);
Array params = RPCConvertValues(strMethod, strParams);
UniValue params = RPCConvertValues(strMethod, strParams);
// Execute and handle connection failures with -rpcwait
const bool fWait = GetBoolArg("-rpcwait", false);
do {
try {
const Object reply = CallRPC(strMethod, params);
const UniValue reply = CallRPC(strMethod, params);
// Parse reply
const Value& result = find_value(reply, "result");
const Value& error = find_value(reply, "error");
const UniValue& result = find_value(reply, "result");
const UniValue& error = find_value(reply, "error");
if (error.type() != null_type) {
if (!error.isNull()) {
// Error
const int code = find_value(error.get_obj(), "code").get_int();
int code = error["code"].get_int();
if (fWait && code == RPC_IN_WARMUP)
throw CConnectionFailed("server in warmup");
strPrint = "error: " + write_string(error, false);
strPrint = "error: " + error.write();
nRet = abs(code);
} else {
// Result
if (result.type() == null_type)
if (result.isNull())
strPrint = "";
else if (result.type() == str_type)
else if (result.isStr())
strPrint = result.get_str();
else
strPrint = write_string(result, true);
strPrint = result.write(2);
}
// Connection succeeded, no need to retry.
break;
}

View File

@ -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");

View File

@ -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();
}

View File

@ -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<typename T, typename U>
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());

View File

@ -1,17 +0,0 @@
#include <gtest/gtest.h>
#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<char> 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);
}

View File

@ -57,18 +57,15 @@ void expect_ser_test_vector(B& b, const C& c, const A& tree) {
template<typename Tree, typename Witness>
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<Witness> 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<default_r1cs_ppzksnark_pp> 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<ZCTestingIncrementalMerkleTree, ZCTestingIncrementalWitness>(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.

View File

@ -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<curve_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<curve_G2>() == e);
}
}

View File

@ -1,6 +1,5 @@
#include <gtest/gtest.h>
#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());
}

View File

@ -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.

View File

@ -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

View File

@ -1,54 +0,0 @@
#ifndef JSON_SPIRIT_ERROR_POSITION
#define JSON_SPIRIT_ERROR_POSITION
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
namespace json_spirit
{
// An Error_position exception is thrown by the "read_or_throw" functions below on finding an error.
// Note the "read_or_throw" functions are around 3 times slower than the standard functions "read"
// functions that return a bool.
//
struct Error_position
{
Error_position();
Error_position( unsigned int line, unsigned int column, const std::string& reason );
bool operator==( const Error_position& lhs ) const;
unsigned int line_;
unsigned int column_;
std::string reason_;
};
inline Error_position::Error_position()
: line_( 0 )
, column_( 0 )
{
}
inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason )
: line_( line )
, column_( column )
, reason_( reason )
{
}
inline bool Error_position::operator==( const Error_position& lhs ) const
{
if( this == &lhs ) return true;
return ( reason_ == lhs.reason_ ) &&
( line_ == lhs.line_ ) &&
( column_ == lhs.column_ );
}
}
#endif

View File

@ -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

View File

@ -1,62 +0,0 @@
#ifndef JSON_SPIRIT_READER
#define JSON_SPIRIT_READER
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_value.h"
#include "json_spirit_error_position.h"
#include <iostream>
namespace json_spirit
{
// functions to reads a JSON values
bool read( const std::string& s, Value& value );
bool read( std::istream& is, Value& value );
bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );
void read_or_throw( const std::string& s, Value& value );
void read_or_throw( std::istream& is, Value& value );
void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );
#ifndef BOOST_NO_STD_WSTRING
bool read( const std::wstring& s, wValue& value );
bool read( std::wistream& is, wValue& value );
bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );
void read_or_throw( const std::wstring& s, wValue& value );
void read_or_throw( std::wistream& is, wValue& value );
void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );
#endif
bool read( const std::string& s, mValue& value );
bool read( std::istream& is, mValue& value );
bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );
void read_or_throw( const std::string& s, mValue& value );
void read_or_throw( std::istream& is, mValue& value );
void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );
#ifndef BOOST_NO_STD_WSTRING
bool read( const std::wstring& s, wmValue& value );
bool read( std::wistream& is, wmValue& value );
bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );
void read_or_throw( const std::wstring& s, wmValue& value );
void read_or_throw( std::wistream& is, wmValue& value );
void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );
#endif
}
#endif

View File

@ -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 <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION >= 103800
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/spirit/include/classic_escape_char.hpp>
#include <boost/spirit/include/classic_multi_pass.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#define spirit_namespace boost::spirit::classic
#else
#include <boost/spirit/core.hpp>
#include <boost/spirit/utility/confix.hpp>
#include <boost/spirit/utility/escape_char.hpp>
#include <boost/spirit/iterator/multi_pass.hpp>
#include <boost/spirit/iterator/position_iterator.hpp>
#define spirit_namespace boost::spirit
#endif
namespace json_spirit
{
const spirit_namespace::int_parser < int64_t > int64_p = spirit_namespace::int_parser < int64_t >();
const spirit_namespace::uint_parser< uint64_t > uint64_p = spirit_namespace::uint_parser< uint64_t >();
template< class Iter_type >
bool is_eq( Iter_type first, Iter_type last, const char* c_str )
{
for( Iter_type i = first; i != last; ++i, ++c_str )
{
if( *c_str == 0 ) return false;
if( *i != *c_str ) return false;
}
return true;
}
template< class Char_type >
Char_type hex_to_num( const Char_type c )
{
if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0';
if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10;
if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10;
return 0;
}
template< class Char_type, class Iter_type >
Char_type hex_str_to_char( Iter_type& begin )
{
const Char_type c1( *( ++begin ) );
const Char_type c2( *( ++begin ) );
return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 );
}
template< class Char_type, class Iter_type >
Char_type unicode_str_to_char( Iter_type& begin )
{
const Char_type c1( *( ++begin ) );
const Char_type c2( *( ++begin ) );
const Char_type c3( *( ++begin ) );
const Char_type c4( *( ++begin ) );
return ( hex_to_num( c1 ) << 12 ) +
( hex_to_num( c2 ) << 8 ) +
( hex_to_num( c3 ) << 4 ) +
hex_to_num( c4 );
}
template< class String_type >
void append_esc_char_and_incr_iter( String_type& s,
typename String_type::const_iterator& begin,
typename String_type::const_iterator end )
{
typedef typename String_type::value_type Char_type;
const Char_type c2( *begin );
switch( c2 )
{
case 't': s += '\t'; break;
case 'b': s += '\b'; break;
case 'f': s += '\f'; break;
case 'n': s += '\n'; break;
case 'r': s += '\r'; break;
case '\\': s += '\\'; break;
case '/': s += '/'; break;
case '"': s += '"'; break;
case 'x':
{
if( end - begin >= 3 ) // expecting "xHH..."
{
s += hex_str_to_char< Char_type >( begin );
}
break;
}
case 'u':
{
if( end - begin >= 5 ) // expecting "uHHHH..."
{
s += unicode_str_to_char< Char_type >( begin );
}
break;
}
}
}
template< class String_type >
String_type substitute_esc_chars( typename String_type::const_iterator begin,
typename String_type::const_iterator end )
{
typedef typename String_type::const_iterator Iter_type;
if( end - begin < 2 ) return String_type( begin, end );
String_type result;
result.reserve( end - begin );
const Iter_type end_minus_1( end - 1 );
Iter_type substr_start = begin;
Iter_type i = begin;
for( ; i < end_minus_1; ++i )
{
if( *i == '\\' )
{
result.append( substr_start, i );
++i; // skip the '\'
append_esc_char_and_incr_iter( result, i, end );
substr_start = i + 1;
}
}
result.append( substr_start, end );
return result;
}
template< class String_type >
String_type get_str_( typename String_type::const_iterator begin,
typename String_type::const_iterator end )
{
assert( end - begin >= 2 );
typedef typename String_type::const_iterator Iter_type;
Iter_type str_without_quotes( ++begin );
Iter_type end_without_quotes( --end );
return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes );
}
inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end )
{
return get_str_< std::string >( begin, end );
}
inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end )
{
return get_str_< std::wstring >( begin, end );
}
template< class String_type, class Iter_type >
String_type get_str( Iter_type begin, Iter_type end )
{
const String_type tmp( begin, end ); // convert multipass iterators to string iterators
return get_str( tmp.begin(), tmp.end() );
}
// this class's methods get called by the spirit parse resulting
// in the creation of a JSON object or array
//
// NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator
//
template< class Value_type, class Iter_type >
class Semantic_actions
{
public:
typedef typename Value_type::Config_type Config_type;
typedef typename Config_type::String_type String_type;
typedef typename Config_type::Object_type Object_type;
typedef typename Config_type::Array_type Array_type;
typedef typename String_type::value_type Char_type;
Semantic_actions( Value_type& value )
: value_( value )
, current_p_( 0 )
{
}
void begin_obj( Char_type c )
{
assert( c == '{' );
begin_compound< Object_type >();
}
void end_obj( Char_type c )
{
assert( c == '}' );
end_compound();
}
void begin_array( Char_type c )
{
assert( c == '[' );
begin_compound< Array_type >();
}
void end_array( Char_type c )
{
assert( c == ']' );
end_compound();
}
void new_name( Iter_type begin, Iter_type end )
{
assert( current_p_->type() == obj_type );
name_ = get_str< String_type >( begin, end );
}
void new_str( Iter_type begin, Iter_type end )
{
add_to_current( get_str< String_type >( begin, end ) );
}
void new_true( Iter_type begin, Iter_type end )
{
assert( is_eq( begin, end, "true" ) );
add_to_current( true );
}
void new_false( Iter_type begin, Iter_type end )
{
assert( is_eq( begin, end, "false" ) );
add_to_current( false );
}
void new_null( Iter_type begin, Iter_type end )
{
assert( is_eq( begin, end, "null" ) );
add_to_current( Value_type() );
}
void new_int( int64_t i )
{
add_to_current( i );
}
void new_uint64( uint64_t ui )
{
add_to_current( ui );
}
void new_real( double d )
{
add_to_current( d );
}
private:
Semantic_actions& operator=( const Semantic_actions& );
// to prevent "assignment operator could not be generated" warning
Value_type* add_first( const Value_type& value )
{
assert( current_p_ == 0 );
value_ = value;
current_p_ = &value_;
return current_p_;
}
template< class Array_or_obj >
void begin_compound()
{
if( current_p_ == 0 )
{
add_first( Array_or_obj() );
}
else
{
// 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 &current_p_->get_array().back();
}
assert( current_p_->type() == obj_type );
return &Config_type::add( current_p_->get_obj(), name_, value );
}
Value_type& value_; // this is the object or array that is being created
Value_type* current_p_; // the child object or array that is currently being constructed
std::vector< Value_type* > stack_; // previous child objects and arrays
String_type name_; // of current name/value pair
};
template< typename Iter_type >
void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason )
{
throw Error_position( i.get_position().line, i.get_position().column, reason );
}
template< typename Iter_type >
void throw_error( Iter_type i, const std::string& reason )
{
throw reason;
}
// the spirit grammer
//
template< class Value_type, class Iter_type >
class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > >
{
public:
typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t;
Json_grammer( Semantic_actions_t& semantic_actions )
: actions_( semantic_actions )
{
}
static void throw_not_value( Iter_type begin, Iter_type end )
{
throw_error( begin, "not a value" );
}
static void throw_not_array( Iter_type begin, Iter_type end )
{
throw_error( begin, "not an array" );
}
static void throw_not_object( Iter_type begin, Iter_type end )
{
throw_error( begin, "not an object" );
}
static void throw_not_pair( Iter_type begin, Iter_type end )
{
throw_error( begin, "not a pair" );
}
static void throw_not_colon( Iter_type begin, Iter_type end )
{
throw_error( begin, "no colon in pair" );
}
static void throw_not_string( Iter_type begin, Iter_type end )
{
throw_error( begin, "not a string" );
}
template< typename ScannerT >
class definition
{
public:
definition( const Json_grammer& self )
{
using namespace spirit_namespace;
typedef typename Value_type::String_type::value_type Char_type;
// first we convert the semantic action class methods to functors with the
// parameter signature expected by spirit
typedef boost::function< void( Char_type ) > Char_action;
typedef boost::function< void( Iter_type, Iter_type ) > Str_action;
typedef boost::function< void( double ) > Real_action;
typedef boost::function< void( int64_t ) > Int_action;
typedef boost::function< void( uint64_t ) > Uint64_action;
Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) );
Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) );
Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) );
Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) );
Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) );
Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) );
Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) );
Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) );
Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) );
Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) );
Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) );
Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) );
// actual grammer
json_
= value_ | eps_p[ &throw_not_value ]
;
value_
= string_[ new_str ]
| number_
| object_
| array_
| str_p( "true" ) [ new_true ]
| str_p( "false" )[ new_false ]
| str_p( "null" ) [ new_null ]
;
object_
= ch_p('{')[ begin_obj ]
>> !members_
>> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] )
;
members_
= pair_ >> *( ',' >> pair_ )
;
pair_
= string_[ new_name ]
>> ( ':' | eps_p[ &throw_not_colon ] )
>> ( value_ | eps_p[ &throw_not_value ] )
;
array_
= ch_p('[')[ begin_array ]
>> !elements_
>> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] )
;
elements_
= value_ >> *( ',' >> value_ )
;
string_
= lexeme_d // this causes white space inside a string to be retained
[
confix_p
(
'"',
*lex_escape_ch_p,
'"'
)
]
;
number_
= strict_real_p[ new_real ]
| int64_p [ new_int ]
| uint64_p [ new_uint64 ]
;
}
spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, string_, number_;
const spirit_namespace::rule< ScannerT >& start() const { return json_; }
};
private:
Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning
Semantic_actions_t& actions_;
};
template< class Iter_type, class Value_type >
Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )
{
Semantic_actions< Value_type, Iter_type > semantic_actions( value );
const spirit_namespace::parse_info< Iter_type > info =
spirit_namespace::parse( begin, end,
Json_grammer< Value_type, Iter_type >( semantic_actions ) >> spirit_namespace::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

View File

@ -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

View File

@ -1,61 +0,0 @@
#ifndef JSON_SPIRIT_UTILS
#define JSON_SPIRIT_UTILS
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_value.h"
#include <map>
namespace json_spirit
{
template< class Obj_t, class Map_t >
void obj_to_map( const Obj_t& obj, Map_t& mp_obj )
{
mp_obj.clear();
for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i )
{
mp_obj[ i->name_ ] = i->value_;
}
}
template< class Obj_t, class Map_t >
void map_to_obj( const Map_t& mp_obj, Obj_t& obj )
{
obj.clear();
for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i )
{
obj.push_back( typename Obj_t::value_type( i->first, i->second ) );
}
}
typedef std::map< std::string, Value > Mapped_obj;
#ifndef BOOST_NO_STD_WSTRING
typedef std::map< std::wstring, wValue > wMapped_obj;
#endif
template< class Object_type, class String_type >
const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name )
{
for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i )
{
if( i->name_ == name )
{
return i->value_;
}
}
return Object_type::value_type::Value_type::null;
}
}
#endif

View File

@ -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"

View File

@ -1,534 +0,0 @@
#ifndef JSON_SPIRIT_VALUE
#define JSON_SPIRIT_VALUE
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <map>
#include <string>
#include <cassert>
#include <sstream>
#include <stdexcept>
#include <stdint.h>
#include <boost/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
namespace json_spirit
{
enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
static const char* Value_type_name[]={"obj", "array", "str", "bool", "int", "real", "null"};
template< class Config > // Config determines whether the value uses std::string or std::wstring and
// whether JSON Objects are represented as vectors or maps
class Value_impl
{
public:
typedef Config Config_type;
typedef typename Config::String_type String_type;
typedef typename Config::Object_type Object;
typedef typename Config::Array_type Array;
typedef typename String_type::const_pointer Const_str_ptr; // eg const char*
Value_impl(); // creates null value
Value_impl( Const_str_ptr value );
Value_impl( const String_type& value );
Value_impl( const Object& value );
Value_impl( const Array& value );
Value_impl( bool value );
Value_impl( int value );
Value_impl( int64_t value );
Value_impl( uint64_t value );
Value_impl( double value );
Value_impl( const Value_impl& other );
bool operator==( const Value_impl& lhs ) const;
Value_impl& operator=( const Value_impl& lhs );
Value_type type() const;
bool is_uint64() const;
bool is_null() const;
const String_type& get_str() const;
const Object& get_obj() const;
const Array& get_array() const;
bool get_bool() const;
int get_int() const;
int64_t get_int64() const;
uint64_t get_uint64() const;
double get_real() const;
Object& get_obj();
Array& get_array();
template< typename T > T get_value() const; // example usage: int i = value.get_value< int >();
// or double d = value.get_value< double >();
static const Value_impl null;
private:
void check_type( const Value_type vtype ) const;
typedef boost::variant< String_type,
boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >,
bool, int64_t, double > Variant;
Value_type type_;
Variant v_;
bool is_uint64_;
};
// vector objects
template< class Config >
struct Pair_impl
{
typedef typename Config::String_type String_type;
typedef typename Config::Value_type Value_type;
Pair_impl( const String_type& name, const Value_type& value );
bool operator==( const Pair_impl& lhs ) const;
String_type name_;
Value_type value_;
};
template< class String >
struct Config_vector
{
typedef String String_type;
typedef Value_impl< Config_vector > Value_type;
typedef Pair_impl < Config_vector > Pair_type;
typedef std::vector< Value_type > Array_type;
typedef std::vector< Pair_type > Object_type;
static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
{
obj.push_back( Pair_type( name , value ) );
return obj.back().value_;
}
static String_type get_name( const Pair_type& pair )
{
return pair.name_;
}
static Value_type get_value( const Pair_type& pair )
{
return pair.value_;
}
};
// typedefs for ASCII
typedef Config_vector< std::string > Config;
typedef Config::Value_type Value;
typedef Config::Pair_type Pair;
typedef Config::Object_type Object;
typedef Config::Array_type Array;
// typedefs for Unicode
#ifndef BOOST_NO_STD_WSTRING
typedef Config_vector< std::wstring > wConfig;
typedef wConfig::Value_type wValue;
typedef wConfig::Pair_type wPair;
typedef wConfig::Object_type wObject;
typedef wConfig::Array_type wArray;
#endif
// map objects
template< class String >
struct Config_map
{
typedef String String_type;
typedef Value_impl< Config_map > Value_type;
typedef std::vector< Value_type > Array_type;
typedef std::map< String_type, Value_type > Object_type;
typedef typename Object_type::value_type Pair_type;
static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
{
return obj[ name ] = value;
}
static String_type get_name( const Pair_type& pair )
{
return pair.first;
}
static Value_type get_value( const Pair_type& pair )
{
return pair.second;
}
};
// typedefs for ASCII
typedef Config_map< std::string > mConfig;
typedef mConfig::Value_type mValue;
typedef mConfig::Object_type mObject;
typedef mConfig::Array_type mArray;
// typedefs for Unicode
#ifndef BOOST_NO_STD_WSTRING
typedef Config_map< std::wstring > wmConfig;
typedef wmConfig::Value_type wmValue;
typedef wmConfig::Object_type wmObject;
typedef wmConfig::Array_type wmArray;
#endif
///////////////////////////////////////////////////////////////////////////////////////////////
//
// implementation
template< class Config >
const Value_impl< Config > Value_impl< Config >::null;
template< class Config >
Value_impl< Config >::Value_impl()
: type_( null_type )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Const_str_ptr value )
: type_( str_type )
, v_( String_type( value ) )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const String_type& value )
: type_( str_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Object& value )
: type_( obj_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Array& value )
: type_( array_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( bool value )
: type_( bool_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( int value )
: type_( int_type )
, v_( static_cast< int64_t >( value ) )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( int64_t value )
: type_( int_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( uint64_t value )
: type_( int_type )
, v_( static_cast< int64_t >( value ) )
, is_uint64_( true )
{
}
template< class Config >
Value_impl< Config >::Value_impl( double value )
: type_( real_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Value_impl< Config >& other )
: type_( other.type() )
, v_( other.v_ )
, is_uint64_( other.is_uint64_ )
{
}
template< class Config >
Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs )
{
Value_impl tmp( lhs );
std::swap( type_, tmp.type_ );
std::swap( v_, tmp.v_ );
std::swap( is_uint64_, tmp.is_uint64_ );
return *this;
}
template< class Config >
bool Value_impl< Config >::operator==( const Value_impl& lhs ) const
{
if( this == &lhs ) return true;
if( type() != lhs.type() ) return false;
return v_ == lhs.v_;
}
template< class Config >
Value_type Value_impl< Config >::type() const
{
return type_;
}
template< class Config >
bool Value_impl< Config >::is_uint64() const
{
return is_uint64_;
}
template< class Config >
bool Value_impl< Config >::is_null() const
{
return type() == null_type;
}
template< class Config >
void Value_impl< Config >::check_type( const Value_type vtype ) const
{
if( type() != vtype )
{
std::ostringstream os;
///// Bitcoin: Tell the types by name instead of by number
os << "value is type " << Value_type_name[type()] << ", expected " << Value_type_name[vtype];
throw std::runtime_error( os.str() );
}
}
template< class Config >
const typename Config::String_type& Value_impl< Config >::get_str() const
{
check_type( str_type );
return *boost::get< String_type >( &v_ );
}
template< class Config >
const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const
{
check_type( obj_type );
return *boost::get< Object >( &v_ );
}
template< class Config >
const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const
{
check_type( array_type );
return *boost::get< Array >( &v_ );
}
template< class Config >
bool Value_impl< Config >::get_bool() const
{
check_type( bool_type );
return boost::get< bool >( v_ );
}
template< class Config >
int Value_impl< Config >::get_int() const
{
check_type( int_type );
return static_cast< int >( get_int64() );
}
template< class Config >
int64_t Value_impl< Config >::get_int64() const
{
check_type( int_type );
return boost::get< int64_t >( v_ );
}
template< class Config >
uint64_t Value_impl< Config >::get_uint64() const
{
check_type( int_type );
return static_cast< uint64_t >( get_int64() );
}
template< class Config >
double Value_impl< Config >::get_real() const
{
if( type() == int_type )
{
return is_uint64() ? static_cast< double >( get_uint64() )
: static_cast< double >( get_int64() );
}
check_type( real_type );
return boost::get< double >( v_ );
}
template< class Config >
typename Value_impl< Config >::Object& Value_impl< Config >::get_obj()
{
check_type( obj_type );
return *boost::get< Object >( &v_ );
}
template< class Config >
typename Value_impl< Config >::Array& Value_impl< Config >::get_array()
{
check_type( array_type );
return *boost::get< Array >( &v_ );
}
template< class Config >
Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value )
: name_( name )
, value_( value )
{
}
template< class Config >
bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const
{
if( this == &lhs ) return true;
return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ );
}
// converts a C string, ie. 8 bit char array, to a string object
//
template < class String_type >
String_type to_str( const char* c_str )
{
String_type result;
for( const char* p = c_str; *p != 0; ++p )
{
result += *p;
}
return result;
}
//
namespace internal_
{
template< typename T >
struct Type_to_type
{
};
template< class Value >
int get_value( const Value& value, Type_to_type< int > )
{
return value.get_int();
}
template< class Value >
int64_t get_value( const Value& value, Type_to_type< int64_t > )
{
return value.get_int64();
}
template< class Value >
uint64_t get_value( const Value& value, Type_to_type< uint64_t > )
{
return value.get_uint64();
}
template< class Value >
double get_value( const Value& value, Type_to_type< double > )
{
return value.get_real();
}
template< class Value >
typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > )
{
return value.get_str();
}
template< class Value >
typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > )
{
return value.get_array();
}
template< class Value >
typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > )
{
return value.get_obj();
}
template< class Value >
bool get_value( const Value& value, Type_to_type< bool > )
{
return value.get_bool();
}
}
template< class Config >
template< typename T >
T Value_impl< Config >::get_value() const
{
return internal_::get_value( *this, internal_::Type_to_type< T >() );
}
}
#endif

View File

@ -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

View File

@ -1,50 +0,0 @@
#ifndef JSON_SPIRIT_WRITER
#define JSON_SPIRIT_WRITER
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_value.h"
#include <iostream>
namespace json_spirit
{
// functions to convert JSON Values to text,
// the "formatted" versions add whitespace to format the output nicely
void write ( const Value& value, std::ostream& os );
void write_formatted( const Value& value, std::ostream& os );
std::string write ( const Value& value );
std::string write_formatted( const Value& value );
#ifndef BOOST_NO_STD_WSTRING
void write ( const wValue& value, std::wostream& os );
void write_formatted( const wValue& value, std::wostream& os );
std::wstring write ( const wValue& value );
std::wstring write_formatted( const wValue& value );
#endif
void write ( const mValue& value, std::ostream& os );
void write_formatted( const mValue& value, std::ostream& os );
std::string write ( const mValue& value );
std::string write_formatted( const mValue& value );
#ifndef BOOST_NO_STD_WSTRING
void write ( const wmValue& value, std::wostream& os );
void write_formatted( const wmValue& value, std::wostream& os );
std::wstring write ( const wmValue& value );
std::wstring write_formatted( const wmValue& value );
#endif
}
#endif

View File

@ -1,249 +0,0 @@
#ifndef JSON_SPIRIT_WRITER_TEMPLATE
#define JSON_SPIRIT_WRITER_TEMPLATE
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#include "json_spirit_value.h"
#include <cassert>
#include <sstream>
#include <iomanip>
namespace json_spirit
{
inline char to_hex_char( unsigned int c )
{
assert( c <= 0xF );
const char ch = static_cast< char >( c );
if( ch < 10 ) return '0' + ch;
return 'A' - 10 + ch;
}
template< class String_type >
String_type non_printable_to_string( unsigned int c )
{
// Silence the warning: typedef Char_type locally defined but not used [-Wunused-local-typedefs]
// typedef typename String_type::value_type Char_type;
String_type result( 6, '\\' );
result[1] = 'u';
result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
result[ 2 ] = to_hex_char( c & 0x000F );
return result;
}
template< typename Char_type, class String_type >
bool add_esc_char( Char_type c, String_type& s )
{
switch( c )
{
case '"': s += to_str< String_type >( "\\\"" ); return true;
case '\\': s += to_str< String_type >( "\\\\" ); return true;
case '\b': s += to_str< String_type >( "\\b" ); return true;
case '\f': s += to_str< String_type >( "\\f" ); return true;
case '\n': s += to_str< String_type >( "\\n" ); return true;
case '\r': s += to_str< String_type >( "\\r" ); return true;
case '\t': s += to_str< String_type >( "\\t" ); return true;
}
return false;
}
template< class String_type >
String_type add_esc_chars( const String_type& s )
{
typedef typename String_type::const_iterator Iter_type;
typedef typename String_type::value_type Char_type;
String_type result;
const Iter_type end( s.end() );
for( Iter_type i = s.begin(); i != end; ++i )
{
const Char_type c( *i );
if( add_esc_char( c, result ) ) continue;
const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
if( iswprint( unsigned_c ) )
{
result += c;
}
else
{
result += non_printable_to_string< String_type >( unsigned_c );
}
}
return result;
}
// this class generates the JSON text,
// it keeps track of the indentation level etc.
//
template< class Value_type, class Ostream_type >
class Generator
{
typedef typename Value_type::Config_type Config_type;
typedef typename Config_type::String_type String_type;
typedef typename Config_type::Object_type Object_type;
typedef typename Config_type::Array_type Array_type;
typedef typename String_type::value_type Char_type;
typedef typename Object_type::value_type Obj_member_type;
public:
Generator( const Value_type& value, Ostream_type& os, bool pretty )
: os_( os )
, indentation_level_( 0 )
, pretty_( pretty )
{
output( value );
}
private:
void output( const Value_type& value )
{
switch( value.type() )
{
case obj_type: output( value.get_obj() ); break;
case array_type: output( value.get_array() ); break;
case str_type: output( value.get_str() ); break;
case bool_type: output( value.get_bool() ); break;
case int_type: output_int( value ); break;
/// Bitcoin: Added std::fixed and changed precision from 16 to 8
case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8)
<< value.get_real(); break;
case null_type: os_ << "null"; break;
default: assert( false );
}
}
void output( const Object_type& obj )
{
output_array_or_obj( obj, '{', '}' );
}
void output( const Array_type& arr )
{
output_array_or_obj( arr, '[', ']' );
}
void output( const Obj_member_type& member )
{
output( Config_type::get_name( member ) ); space();
os_ << ':'; space();
output( Config_type::get_value( member ) );
}
void output_int( const Value_type& value )
{
if( value.is_uint64() )
{
os_ << value.get_uint64();
}
else
{
os_ << value.get_int64();
}
}
void output( const String_type& s )
{
os_ << '"' << add_esc_chars( s ) << '"';
}
void output( bool b )
{
os_ << to_str< String_type >( b ? "true" : "false" );
}
template< class T >
void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
{
os_ << start_char; new_line();
++indentation_level_;
for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
{
indent(); output( *i );
typename T::const_iterator next = i;
if( ++next != t.end())
{
os_ << ',';
}
new_line();
}
--indentation_level_;
indent(); os_ << end_char;
}
void indent()
{
if( !pretty_ ) return;
for( int i = 0; i < indentation_level_; ++i )
{
os_ << " ";
}
}
void space()
{
if( pretty_ ) os_ << ' ';
}
void new_line()
{
if( pretty_ ) os_ << '\n';
}
Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
Ostream_type& os_;
int indentation_level_;
bool pretty_;
};
template< class Value_type, class Ostream_type >
void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
{
Generator< Value_type, Ostream_type >( value, os, pretty );
}
template< class Value_type >
typename Value_type::String_type write_string( const Value_type& value, bool pretty )
{
typedef typename Value_type::String_type::value_type Char_type;
std::basic_ostringstream< Char_type > os;
write_stream( value, os, pretty );
return os.str();
}
}
#endif

View File

@ -16,10 +16,10 @@
#include "rpcclient.h"
#include "util.h"
#include "json/json_spirit_value.h"
#include <openssl/crypto.h>
#include "univalue/univalue.h"
#ifdef ENABLE_WALLET
#include <db_cxx.h>
#endif
@ -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<std::string>(args.begin() + 1, args.end())));
// Format result reply
if (result.type() == json_spirit::null_type)
if (result.isNull())
strPrint = "";
else if (result.type() == json_spirit::str_type)
else if (result.isStr())
strPrint = result.get_str();
else
strPrint = write_string(result, true);
strPrint = result.write(2);
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)

View File

@ -16,8 +16,9 @@
#include <boost/algorithm/string.hpp>
#include <boost/dynamic_bitset.hpp>
#include "univalue/univalue.h"
using namespace std;
using namespace json_spirit;
static const int MAX_GETUTXOS_OUTPOINTS = 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;
}

View File

@ -13,13 +13,12 @@
#include <stdint.h>
#include "json/json_spirit_value.h"
#include "univalue/univalue.h"
using namespace json_spirit;
using namespace std;
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
double 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<uint256> 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;
}

View File

@ -11,8 +11,9 @@
#include <set>
#include <stdint.h>
#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<std::string> &strParams)
/** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null)
* as well as objects and arrays.
*/
UniValue ParseNonRFCJSONValue(const std::string& strVal)
{
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<std::string> &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));
}
}

View File

@ -6,10 +6,12 @@
#ifndef BITCOIN_RPCCLIENT_H
#define BITCOIN_RPCCLIENT_H
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
json_spirit::Array RPCConvertValues(const std::string& strMethod, const std::vector<std::string>& strParams);
UniValue RPCConvertValues(const std::string& strMethod, const std::vector<std::string>& strParams);
/** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null)
* as well as objects and arrays.
*/
UniValue ParseNonRFCJSONValue(const std::string& strVal);
#endif // BITCOIN_RPCCLIENT_H

View File

@ -28,10 +28,8 @@
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include "univalue/univalue.h"
using namespace json_spirit;
using namespace std;
/**
@ -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: <hashBestChain><nTransactionsUpdatedLast>
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<uint256, int64_t> 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;

View File

@ -20,12 +20,10 @@
#include <stdint.h>
#include <boost/assign/list_of.hpp>
#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<Object>
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
{
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;
}

View File

@ -16,12 +16,11 @@
#include <boost/foreach.hpp>
#include "json/json_spirit_value.h"
#include "univalue/univalue.h"
using namespace json_spirit;
using namespace std;
Value getconnectioncount(const Array& params, bool fHelp)
UniValue getconnectioncount(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -39,7 +38,7 @@ Value getconnectioncount(const Array& params, bool fHelp)
return (int)vNodes.size();
}
Value ping(const Array& params, bool fHelp)
UniValue ping(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -59,7 +58,7 @@ Value ping(const Array& params, bool fHelp)
pNode->fPingQueued = true;
}
return Value::null;
return NullUniValue;
}
static void CopyNodeStats(std::vector<CNodeStats>& vstats)
@ -75,7 +74,7 @@ static void CopyNodeStats(std::vector<CNodeStats>& vstats)
}
}
Value getpeerinfo(const Array& params, bool fHelp)
UniValue getpeerinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -120,10 +119,10 @@ Value getpeerinfo(const Array& params, bool fHelp)
vector<CNodeStats> vstats;
CopyNodeStats(vstats);
Array ret;
UniValue ret(UniValue::VARR);
BOOST_FOREACH(const CNodeStats& stats, vstats) {
Object obj;
UniValue obj(UniValue::VOBJ);
CNodeStateStats statestats;
bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
obj.push_back(Pair("id", stats.nodeid));
@ -151,7 +150,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("banscore", statestats.nMisbehavior));
obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
Array heights;
UniValue heights(UniValue::VARR);
BOOST_FOREACH(int height, statestats.vHeightInFlight) {
heights.push_back(height);
}
@ -165,7 +164,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
return ret;
}
Value addnode(const Array& params, bool fHelp)
UniValue addnode(const UniValue& params, bool fHelp)
{
string strCommand;
if (params.size() == 2)
@ -190,7 +189,7 @@ Value addnode(const Array& params, bool fHelp)
{
CAddress addr;
OpenNetworkConnection(addr, NULL, strNode.c_str());
return Value::null;
return NullUniValue;
}
LOCK(cs_vAddedNodes);
@ -212,10 +211,10 @@ Value addnode(const Array& params, bool fHelp)
vAddedNodes.erase(it);
}
return Value::null;
return NullUniValue;
}
Value getaddednodeinfo(const Array& params, bool fHelp)
UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -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<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
{
Object obj;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("addednode", it->first));
Array addresses;
UniValue addresses(UniValue::VARR);
bool fConnected = false;
BOOST_FOREACH(CService& addrNode, it->second)
{
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<NET_MAX; ++n)
{
enum Network network = static_cast<enum Network>(n);
if(network == NET_UNROUTABLE)
continue;
proxyType proxy;
Object obj;
UniValue obj(UniValue::VOBJ);
GetProxy(network, proxy);
obj.push_back(Pair("name", GetNetworkName(network)));
obj.push_back(Pair("limited", IsLimited(network)));
@ -378,7 +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<string>())));
@ -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));

View File

@ -25,10 +25,10 @@
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/shared_ptr.hpp>
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
using namespace std;
using namespace json_spirit;
//! Number of bytes to allocate and read at most at once in post data
const size_t POST_READ_SIZE = 256 * 1024;
@ -256,20 +256,20 @@ int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
* http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
*/
string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
string JSONRPCRequest(const string& strMethod, const UniValue& params, const UniValue& id)
{
Object request;
UniValue request(UniValue::VOBJ);
request.push_back(Pair("method", strMethod));
request.push_back(Pair("params", params));
request.push_back(Pair("id", id));
return write_string(Value(request), false) + "\n";
return request.write() + "\n";
}
Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id)
{
Object reply;
if (error.type() != null_type)
reply.push_back(Pair("result", Value::null));
UniValue reply(UniValue::VOBJ);
if (!error.isNull())
reply.push_back(Pair("result", NullUniValue));
else
reply.push_back(Pair("result", result));
reply.push_back(Pair("error", error));
@ -277,15 +277,15 @@ Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
return reply;
}
string JSONRPCReply(const Value& result, const Value& error, const Value& id)
string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id)
{
Object reply = JSONRPCReplyObj(result, error, id);
return write_string(Value(reply), false) + "\n";
UniValue reply = JSONRPCReplyObj(result, error, id);
return reply.write() + "\n";
}
Object JSONRPCError(int code, const string& message)
UniValue JSONRPCError(int code, const string& message)
{
Object error;
UniValue error(UniValue::VOBJ);
error.push_back(Pair("code", code));
error.push_back(Pair("message", message));
return error;

View File

@ -16,9 +16,7 @@
#include <boost/asio/ssl.hpp>
#include <boost/filesystem.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
//! HTTP status codes
enum HTTPStatusCode
@ -161,10 +159,10 @@ int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto);
int ReadHTTPHeaders(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet);
int ReadHTTPMessage(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet,
std::string& strMessageRet, int nProto, size_t max_size);
std::string JSONRPCRequest(const std::string& strMethod, const json_spirit::Array& params, const json_spirit::Value& id);
json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
json_spirit::Object JSONRPCError(int code, const std::string& message);
std::string JSONRPCRequest(const std::string& strMethod, const UniValue& params, const UniValue& id);
UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id);
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
UniValue JSONRPCError(int code, const std::string& message);
/** Get name of RPC authentication cookie file */
boost::filesystem::path GetAuthCookieFile();

View File

@ -25,13 +25,12 @@
#include <stdint.h>
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
using namespace json_spirit;
#include "univalue/univalue.h"
using namespace std;
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex)
{
txnouttype type;
vector<CTxDestination> addresses;
@ -49,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<uint256> 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<uint256> 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<CBitcoinAddress> setAddress;
BOOST_FOREACH(const Pair& s, sendTo) {
CBitcoinAddress address(s.name_);
vector<string> addrList = sendTo.getKeys();
BOOST_FOREACH(const string& name_, addrList) {
CBitcoinAddress address(name_);
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
if (setAddress.count(address))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
setAddress.insert(address);
CScript scriptPubKey = GetScriptForDestination(address.Get());
CAmount nAmount = AmountFromValue(s.value_);
CAmount nAmount = AmountFromValue(sendTo[name_]);
CTxOut out(nAmount, scriptPubKey);
rawTx.vout.push_back(out);
@ -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<unsigned char> 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<unsigned char> 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<unsigned char> 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<string, int> 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;

View File

@ -30,10 +30,10 @@
#include <boost/shared_ptr.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/thread.hpp>
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
using namespace boost::asio;
using namespace json_spirit;
using namespace RPCServer;
using namespace std;
@ -81,41 +81,41 @@ void RPCServer::OnPostCommand(boost::function<void (const CRPCCommand&)> slot)
g_rpcSignals.PostCommand.connect(boost::bind(slot, _1));
}
void RPCTypeCheck(const Array& params,
const list<Value_type>& typesExpected,
void RPCTypeCheck(const UniValue& params,
const list<UniValue::VType>& typesExpected,
bool fAllowNull)
{
unsigned int i = 0;
BOOST_FOREACH(Value_type t, typesExpected)
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<string, Value_type>& typesExpected,
void RPCTypeCheckObj(const UniValue& o,
const map<string, UniValue::VType>& typesExpected,
bool fAllowNull)
{
BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected)
BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected)
{
const Value& v = find_value(o, t.first);
if (!fAllowNull && v.type() == null_type)
const UniValue& v = find_value(o, t.first);
if (!fAllowNull && v.isNull())
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
if (!((v.type() == t.second) || (fAllowNull && (v.type() == null_type))))
if (!((v.type() == t.second) || (fAllowNull && (v.isNull()))))
{
string err = strprintf("Expected type %s for %s, got %s",
Value_type_name[t.second], t.first, Value_type_name[v.type()]);
uvTypeName(t.second), t.first, uvTypeName(v.type()));
throw JSONRPCError(RPC_TYPE_ERROR, err);
}
}
@ -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<unsigned char> ParseHexV(const Value& v, string strName)
vector<unsigned char> ParseHexV(const UniValue& v, string strName)
{
string strHex;
if (v.type() == str_type)
if (v.isStr())
strHex = v.get_str();
if (!IsHex(strHex))
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
return ParseHex(strHex);
}
vector<unsigned char> ParseHexO(const Object& o, string strKey)
vector<unsigned char> ParseHexO(const UniValue& o, string strKey)
{
return ParseHexV(find_value(o, strKey), strKey);
}
@ -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<string, string>& mapHeaders)
return TimingResistantEqual(strUserPass, strRPCUserColonPass);
}
void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
void ErrorReply(std::ostream& stream, const UniValue& objError, const UniValue& id)
{
// Send error reply from json-rpc error object
int nStatus = HTTP_INTERNAL_SERVER_ERROR;
int code = find_value(objError, "code").get_int();
if (code == RPC_INVALID_REQUEST) nStatus = HTTP_BAD_REQUEST;
else if (code == RPC_METHOD_NOT_FOUND) nStatus = HTTP_NOT_FOUND;
string strReply = JSONRPCReply(Value::null, objError, id);
string strReply = JSONRPCReply(NullUniValue, objError, id);
stream << HTTPReply(nStatus, strReply, false) << std::flush;
}
@ -862,76 +862,76 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
class JSONRequest
{
public:
Value id;
UniValue id;
string strMethod;
Array params;
UniValue params;
JSONRequest() { id = Value::null; }
void parse(const Value& valRequest);
JSONRequest() { id = NullUniValue; }
void parse(const UniValue& valRequest);
};
void JSONRequest::parse(const Value& valRequest)
void JSONRequest::parse(const UniValue& valRequest)
{
// Parse request
if (valRequest.type() != obj_type)
if (!valRequest.isObject())
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
const Object& request = valRequest.get_obj();
const UniValue& request = valRequest.get_obj();
// Parse id now so errors from here on will have the id
id = find_value(request, "id");
// Parse method
Value valMethod = find_value(request, "method");
if (valMethod.type() == null_type)
UniValue valMethod = find_value(request, "method");
if (valMethod.isNull())
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
if (valMethod.type() != str_type)
if (!valMethod.isStr())
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getblocktemplate")
LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
// Parse params
Value valParams = find_value(request, "params");
if (valParams.type() == array_type)
UniValue valParams = find_value(request, "params");
if (valParams.isArray())
params = valParams.get_array();
else if (valParams.type() == null_type)
params = Array();
else if (valParams.isNull())
params = UniValue(UniValue::VARR);
else
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array");
}
static Object JSONRPCExecOne(const Value& req)
static UniValue JSONRPCExecOne(const UniValue& req)
{
Object rpc_result;
UniValue rpc_result(UniValue::VOBJ);
JSONRequest jreq;
try {
jreq.parse(req);
Value result = tableRPC.execute(jreq.strMethod, jreq.params);
rpc_result = JSONRPCReplyObj(result, Value::null, jreq.id);
UniValue result = tableRPC.execute(jreq.strMethod, jreq.params);
rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
}
catch (const Object& objError)
catch (const UniValue& objError)
{
rpc_result = JSONRPCReplyObj(Value::null, objError, jreq.id);
rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
}
catch (const std::exception& e)
{
rpc_result = JSONRPCReplyObj(Value::null,
rpc_result = JSONRPCReplyObj(NullUniValue,
JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
}
return rpc_result;
}
static string JSONRPCExecBatch(const Array& vReq)
static string JSONRPCExecBatch(const UniValue& vReq)
{
Array ret;
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 &params) const
UniValue CRPCTable::execute(const std::string &strMethod, const UniValue &params) const
{
// Find method
const CRPCCommand *pcmd = tableRPC[strMethod];

View File

@ -16,9 +16,9 @@
#include <string>
#include <memory>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
#include <boost/function.hpp>
#include "univalue/univalue.h"
class 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<json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
/**
* Check for expected keys/value types in an Object.
* Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type));
*/
void RPCTypeCheck(const json_spirit::Object& o,
const std::map<std::string, json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
void RPCTypeCheck(const UniValue& params,
const std::list<UniValue::VType>& typesExpected, bool fAllowNull=false);
/*
Check for expected keys/value types in an Object.
Use like: RPCTypeCheckObj(object, boost::assign::map_list_of("name", str_type)("value", int_type));
*/
void RPCTypeCheckObj(const UniValue& o,
const std::map<std::string, UniValue::VType>& typesExpected, bool fAllowNull=false);
/**
* Run func nSeconds from now. Uses boost deadline timers.
@ -95,7 +96,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
//! Convert boost::asio address to CNetAddr
extern CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address);
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
typedef UniValue(*rpcfn_type)(const UniValue& params, bool fHelp);
class CRPCCommand
{
@ -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 &params) const;
UniValue execute(const std::string &method, const UniValue &params) 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<unsigned char> ParseHexV(const json_spirit::Value& v, std::string strName);
extern std::vector<unsigned char> ParseHexO(const json_spirit::Object& o, std::string strKey);
extern uint256 ParseHashV(const UniValue& v, std::string strName);
extern uint256 ParseHashO(const UniValue& o, std::string strKey);
extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
extern void InitRPCMining();
extern void ShutdownRPCMining();
extern int64_t nWalletUnlockTime;
extern CAmount AmountFromValue(const json_spirit::Value& value);
extern json_spirit::Value ValueFromAmount(const CAmount& amount);
extern CAmount AmountFromValue(const UniValue& value);
extern UniValue ValueFromAmount(const CAmount& amount);
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
extern 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

View File

@ -27,7 +27,6 @@
#include <boost/filesystem/operations.hpp>
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "key.h"
#include "alertkeys.h"

View File

@ -17,23 +17,20 @@
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
using namespace json_spirit;
extern Array read_json(const std::string& jsondata);
#include "univalue/univalue.h"
extern UniValue read_json(const std::string& jsondata);
BOOST_FIXTURE_TEST_SUITE(base58_tests, BasicTestingSetup)
// Goal: test low-level base58 encoding functionality
BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
for (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<unsigned char> 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<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
SelectParams(CBaseChainParams::MAIN);
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (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<unsigned char> exp_payload = ParseHex(test[1].get_str());
const Object &metadata = test[2].get_obj();
const UniValue &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
if (isTestnet)
@ -183,12 +178,12 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
// Goal: check that generated keys match test vectors
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
std::vector<unsigned char> result;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (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<unsigned char> exp_payload = ParseHex(test[1].get_str());
const Object &metadata = test[2].get_obj();
const UniValue &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
if (isTestnet)
@ -251,15 +246,14 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
// Goal: check that base58 parsing code is robust against a variety of corrupted data
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
Array tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (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);

View File

@ -13,22 +13,23 @@
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
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<string> 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)

View File

@ -31,15 +31,16 @@
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
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<std::string> 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<std::string> 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<AsyncRPCOperation> 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<AsyncRPCOperation> 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<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany("tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ", {}, {}, 1) );
} catch (const Object& objError) {
} catch (const UniValue& objError) {
BOOST_CHECK( find_error(objError, "No recipients"));
}
try {
std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
std::shared_ptr<AsyncRPCOperation> 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<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
std::shared_ptr<AsyncRPCOperation> 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<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
std::shared_ptr<AsyncRPCOperation> 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

View File

@ -26,12 +26,10 @@
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
using namespace std;
using namespace json_spirit;
// Uncomment if you want to output updated JSON tests.
// #define UPDATE_JSON_TESTS
@ -41,15 +39,15 @@ static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
unsigned int ParseScriptFlags(string strFlags);
string FormatScriptFlags(unsigned int flags);
Array
UniValue
read_json(const std::string& jsondata)
{
Value v;
UniValue v;
if (!read_string(jsondata, v) || v.type() != array_type)
if (!v.read(jsondata) || !v.isArray())
{
BOOST_ERROR("Parse error.");
return Array();
return UniValue(UniValue::VARR);
}
return v.get_array();
}
@ -295,10 +293,10 @@ public:
return *this;
}
Array GetJSON()
UniValue GetJSON()
{
DoPush();
Array array;
UniValue array(UniValue::VARR);
array.push_back(FormatScript(spendTx.vin[0].scriptSig));
array.push_back(FormatScript(creditTx.vout[0].scriptPubKey));
array.push_back(FormatScriptFlags(flags));
@ -582,14 +580,16 @@ BOOST_AUTO_TEST_CASE(script_build)
std::set<std::string> tests_bad;
{
Array json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
Array json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
UniValue json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
UniValue json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
BOOST_FOREACH(Value& tv, json_good) {
tests_good.insert(write_string(Value(tv.get_array()), true));
for (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);

View File

@ -17,12 +17,10 @@
#include <iostream>
#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
using namespace json_spirit;
extern Array read_json(const std::string& jsondata);
#include "univalue/univalue.h"
extern UniValue read_json(const std::string& jsondata);
// Old script.cpp SignatureHash function
uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
@ -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);

View File

@ -23,19 +23,20 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
#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<string, unsigned int> 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<COutPoint, CScript> mapprevOutScriptPubKeys;
Array inputs = test[0].get_array();
UniValue inputs = test[0].get_array();
bool fValid = true;
BOOST_FOREACH(Value& input, inputs)
{
if (input.type() != array_type)
for (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<COutPoint, CScript> mapprevOutScriptPubKeys;
Array inputs = test[0].get_array();
UniValue inputs = test[0].get_array();
bool fValid = true;
BOOST_FOREACH(Value& input, inputs)
{
if (input.type() != array_type)
for (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;

View File

@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
double vd = -7.21;
UniValue v7(vd);
BOOST_CHECK(v7.isNum());
BOOST_CHECK(v7.isReal());
BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21");
string vs("yawn");
@ -63,6 +63,48 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
BOOST_CHECK_EQUAL(v9.getValStr(), "zappa");
}
BOOST_AUTO_TEST_CASE(univalue_typecheck)
{
UniValue v1;
BOOST_CHECK(v1.setNumStr("1"));
BOOST_CHECK(v1.isNum());
BOOST_CHECK_THROW(v1.get_bool(), runtime_error);
UniValue v2;
BOOST_CHECK(v2.setBool(true));
BOOST_CHECK_EQUAL(v2.get_bool(), true);
BOOST_CHECK_THROW(v2.get_int(), runtime_error);
UniValue v3;
BOOST_CHECK(v3.setNumStr("32482348723847471234"));
BOOST_CHECK_THROW(v3.get_int64(), runtime_error);
BOOST_CHECK(v3.setNumStr("1000"));
BOOST_CHECK_EQUAL(v3.get_int64(), 1000);
UniValue v4;
BOOST_CHECK(v4.setNumStr("2147483648"));
BOOST_CHECK_EQUAL(v4.get_int64(), 2147483648);
BOOST_CHECK_THROW(v4.get_int(), runtime_error);
BOOST_CHECK(v4.setNumStr("1000"));
BOOST_CHECK_EQUAL(v4.get_int(), 1000);
BOOST_CHECK_THROW(v4.get_str(), runtime_error);
BOOST_CHECK_EQUAL(v4.get_real(), 1000);
BOOST_CHECK_THROW(v4.get_array(), runtime_error);
BOOST_CHECK_THROW(v4.getKeys(), runtime_error);
BOOST_CHECK_THROW(v4.getValues(), runtime_error);
BOOST_CHECK_THROW(v4.get_obj(), runtime_error);
UniValue v5;
BOOST_CHECK(v5.read("[true, 10]"));
BOOST_CHECK_NO_THROW(v5.get_array());
std::vector<UniValue> vals = v5.getValues();
BOOST_CHECK_THROW(vals[0].get_int(), runtime_error);
BOOST_CHECK_EQUAL(vals[0].get_bool(), true);
BOOST_CHECK_EQUAL(vals[1].get_int(), 10);
BOOST_CHECK_THROW(vals[1].get_bool(), runtime_error);
}
BOOST_AUTO_TEST_CASE(univalue_set)
{
UniValue v(UniValue::VSTR, "foo");
@ -72,20 +114,20 @@ BOOST_AUTO_TEST_CASE(univalue_set)
BOOST_CHECK(v.setObject());
BOOST_CHECK(v.isObject());
BOOST_CHECK_EQUAL(v.count(), 0);
BOOST_CHECK_EQUAL(v.size(), 0);
BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ);
BOOST_CHECK(v.empty());
BOOST_CHECK(v.setArray());
BOOST_CHECK(v.isArray());
BOOST_CHECK_EQUAL(v.count(), 0);
BOOST_CHECK_EQUAL(v.size(), 0);
BOOST_CHECK(v.setStr("zum"));
BOOST_CHECK(v.isStr());
BOOST_CHECK_EQUAL(v.getValStr(), "zum");
BOOST_CHECK(v.setFloat(-1.01));
BOOST_CHECK(v.isNum());
BOOST_CHECK(v.isReal());
BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
BOOST_CHECK(v.setInt((int)1023));
@ -145,7 +187,7 @@ BOOST_AUTO_TEST_CASE(univalue_array)
BOOST_CHECK(arr.push_backV(vec));
BOOST_CHECK_EQUAL(arr.empty(), false);
BOOST_CHECK_EQUAL(arr.count(), 5);
BOOST_CHECK_EQUAL(arr.size(), 5);
BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023");
BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy");
@ -157,7 +199,7 @@ BOOST_AUTO_TEST_CASE(univalue_array)
arr.clear();
BOOST_CHECK(arr.empty());
BOOST_CHECK_EQUAL(arr.count(), 0);
BOOST_CHECK_EQUAL(arr.size(), 0);
}
BOOST_AUTO_TEST_CASE(univalue_object)
@ -197,7 +239,7 @@ BOOST_AUTO_TEST_CASE(univalue_object)
BOOST_CHECK(obj.pushKVs(obj2));
BOOST_CHECK_EQUAL(obj.empty(), false);
BOOST_CHECK_EQUAL(obj.count(), 9);
BOOST_CHECK_EQUAL(obj.size(), 9);
BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100");
BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John");
@ -230,7 +272,7 @@ BOOST_AUTO_TEST_CASE(univalue_object)
objTypes["distance"] = UniValue::VNUM;
objTypes["time"] = UniValue::VNUM;
objTypes["calories"] = UniValue::VNUM;
objTypes["temperature"] = UniValue::VNUM;
objTypes["temperature"] = UniValue::VREAL;
objTypes["cat1"] = UniValue::VNUM;
objTypes["cat2"] = UniValue::VNUM;
BOOST_CHECK(obj.checkObject(objTypes));
@ -240,11 +282,11 @@ BOOST_AUTO_TEST_CASE(univalue_object)
obj.clear();
BOOST_CHECK(obj.empty());
BOOST_CHECK_EQUAL(obj.count(), 0);
BOOST_CHECK_EQUAL(obj.size(), 0);
}
static const char *json1 =
"[1.1,{\"key1\":\"str\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]";
"[1.10000000,{\"key1\":\"str\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]";
BOOST_AUTO_TEST_CASE(univalue_readwrite)
{
@ -255,13 +297,13 @@ BOOST_AUTO_TEST_CASE(univalue_readwrite)
BOOST_CHECK(v.read(strJson1));
BOOST_CHECK(v.isArray());
BOOST_CHECK_EQUAL(v.count(), 2);
BOOST_CHECK_EQUAL(v.size(), 2);
BOOST_CHECK_EQUAL(v[0].getValStr(), "1.1");
BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000");
UniValue obj = v[1];
BOOST_CHECK(obj.isObject());
BOOST_CHECK_EQUAL(obj.count(), 3);
BOOST_CHECK_EQUAL(obj.size(), 3);
BOOST_CHECK(obj["key1"].isStr());
BOOST_CHECK_EQUAL(obj["key1"].getValStr(), "str");

View File

@ -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), "");

View File

@ -4,12 +4,17 @@
#include <stdint.h>
#include <ctype.h>
#include <iomanip>
#include <sstream>
#include <stdexcept> // std::runtime_error
#include "univalue.h"
#include "utilstrencodings.h" // ParseXX
using namespace std;
static const UniValue nullValue;
const UniValue NullUniValue;
void UniValue::clear()
{
@ -78,9 +83,11 @@ bool UniValue::setFloat(double val)
string s;
ostringstream oss;
oss << val;
oss << std::setprecision(16) << val;
return setNumStr(oss.str());
bool ret = setNumStr(oss.str());
typ = VREAL;
return ret;
}
bool UniValue::setStr(const string& val_)
@ -175,11 +182,11 @@ bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t)
const UniValue& UniValue::operator[](const std::string& key) const
{
if (typ != VOBJ)
return nullValue;
return NullUniValue;
int index = findKey(key);
if (index < 0)
return nullValue;
return NullUniValue;
return values[index];
}
@ -187,9 +194,9 @@ const UniValue& UniValue::operator[](const std::string& key) const
const UniValue& UniValue::operator[](unsigned int index) const
{
if (typ != VOBJ && typ != VARR)
return nullValue;
return NullUniValue;
if (index >= values.size())
return nullValue;
return NullUniValue;
return values[index];
}
@ -203,9 +210,95 @@ const char *uvTypeName(UniValue::VType t)
case UniValue::VARR: return "array";
case UniValue::VSTR: return "string";
case UniValue::VNUM: return "number";
case UniValue::VREAL: return "number";
}
// not reached
return NULL;
}
const UniValue& find_value( const UniValue& obj, const std::string& name)
{
for (unsigned int i = 0; i < obj.keys.size(); i++)
{
if( obj.keys[i] == name )
{
return obj.values[i];
}
}
return NullUniValue;
}
std::vector<std::string> UniValue::getKeys() const
{
if (typ != VOBJ)
throw std::runtime_error("JSON value is not an object as expected");
return keys;
}
std::vector<UniValue> UniValue::getValues() const
{
if (typ != VOBJ && typ != VARR)
throw std::runtime_error("JSON value is not an object or array as expected");
return values;
}
bool UniValue::get_bool() const
{
if (typ != VBOOL)
throw std::runtime_error("JSON value is not a boolean as expected");
return getBool();
}
std::string UniValue::get_str() const
{
if (typ != VSTR)
throw std::runtime_error("JSON value is not a string as expected");
return getValStr();
}
int UniValue::get_int() const
{
if (typ != VNUM)
throw std::runtime_error("JSON value is not an integer as expected");
int32_t retval;
if (!ParseInt32(getValStr(), &retval))
throw std::runtime_error("JSON integer out of range");
return retval;
}
int64_t UniValue::get_int64() const
{
if (typ != VNUM)
throw std::runtime_error("JSON value is not an integer as expected");
int64_t retval;
if (!ParseInt64(getValStr(), &retval))
throw std::runtime_error("JSON integer out of range");
return retval;
}
double UniValue::get_real() const
{
if (typ != VREAL && typ != VNUM)
throw std::runtime_error("JSON value is not a number as expected");
double retval;
if (!ParseDouble(getValStr(), &retval))
throw std::runtime_error("JSON double out of range");
return retval;
}
const UniValue& UniValue::get_obj() const
{
if (typ != VOBJ)
throw std::runtime_error("JSON value is not an object as expected");
return *this;
}
const UniValue& UniValue::get_array() const
{
if (typ != VARR)
throw std::runtime_error("JSON value is not an array as expected");
return *this;
}

View File

@ -11,9 +11,12 @@
#include <map>
#include <cassert>
#include <sstream> // .get_int64()
#include <utility> // std::pair
class UniValue {
public:
enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VREAL, VBOOL, };
UniValue() { typ = VNULL; }
UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
@ -26,6 +29,9 @@ public:
UniValue(int64_t val_) {
setInt(val_);
}
UniValue(bool val_) {
setBool(val_);
}
UniValue(int val_) {
setInt(val_);
}
@ -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<std::string,UniValue::VType>& memberTypes);
@ -68,10 +74,11 @@ public:
bool isNull() const { return (typ == VNULL); }
bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
bool isFalse() const { return (!isTrue()); }
bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
bool isBool() const { return (typ == VBOOL); }
bool isStr() const { return (typ == VSTR); }
bool isNum() const { return (typ == VNUM); }
bool isReal() const { return (typ == VREAL); }
bool isArray() const { return (typ == VARR); }
bool isObject() const { return (typ == VOBJ); }
@ -130,8 +137,91 @@ private:
int findKey(const std::string& key) const;
void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
public:
// Strict type-specific getters, these throw std::runtime_error if the
// value is of unexpected type
std::vector<std::string> getKeys() const;
std::vector<UniValue> getValues() const;
bool get_bool() const;
std::string get_str() const;
int get_int() const;
int64_t get_int64() const;
double get_real() const;
const UniValue& get_obj() const;
const UniValue& get_array() const;
enum VType type() const { return getType(); }
bool push_back(std::pair<std::string,UniValue> pear) {
return pushKV(pear.first, pear.second);
}
friend const UniValue& find_value( const UniValue& obj, const std::string& name);
};
//
// The following were added for compatibility with json_spirit.
// Most duplicate other methods, and should be removed.
//
static inline std::pair<std::string,UniValue> Pair(const char *cKey, const char *cVal)
{
std::string key(cKey);
UniValue uVal(cVal);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(const char *cKey, std::string strVal)
{
std::string key(cKey);
UniValue uVal(strVal);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(const char *cKey, uint64_t u64Val)
{
std::string key(cKey);
UniValue uVal(u64Val);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(const char *cKey, int64_t i64Val)
{
std::string key(cKey);
UniValue uVal(i64Val);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(const char *cKey, bool iVal)
{
std::string key(cKey);
UniValue uVal(iVal);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(const char *cKey, int iVal)
{
std::string key(cKey);
UniValue uVal(iVal);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(const char *cKey, double dVal)
{
std::string key(cKey);
UniValue uVal(dVal);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(const char *cKey, const UniValue& uVal)
{
std::string key(cKey);
return std::make_pair(key, uVal);
}
static inline std::pair<std::string,UniValue> Pair(std::string key, const UniValue& uVal)
{
return std::make_pair(key, uVal);
}
enum jtokentype {
JTOK_ERR = -1,
JTOK_NONE = 0, // eof
@ -152,4 +242,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

View File

@ -3,6 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <ctype.h>
#include <iomanip>
#include <sstream>
#include <stdio.h>
#include "univalue.h"
#include "univalue_escapes.h"
@ -59,6 +61,13 @@ string UniValue::write(unsigned int prettyIndent,
case VSTR:
s += "\"" + json_escape(val) + "\"";
break;
case VREAL:
{
std::stringstream ss;
ss << std::showpoint << std::fixed << std::setprecision(8) << get_real();
s += ss.str();
}
break;
case VNUM:
s += val;
break;

View File

@ -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<int32_t>::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<int64_t>::min() &&
n <= std::numeric_limits<int64_t>::max();
}
bool ParseDouble(const std::string& str, double *out)
{
if (!ParsePrechecks(str))
return false;
if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
return false;
char *endp = NULL;
errno = 0; // strtod will not set errno if valid
double n = strtod(str.c_str(), &endp);
if(out) *out = n;
return endp && *endp == 0 && !errno;
}
std::string FormatParagraph(const std::string in, size_t width, size_t indent)
{
std::stringstream out;

View File

@ -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<typename T>
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
{

View File

@ -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<SendManyRecipient> 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<boost::optional < ZCIncrementalWitness>> witnesses;
uint256 anchor;
{
@ -902,7 +907,7 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info)
}
Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, std::vector<JSOutPoint> & outPoints) {
UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, std::vector<JSOutPoint> & outPoints) {
std::vector<boost::optional < ZCIncrementalWitness>> 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<boost::optional < ZCIncrementalWitness>> 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<unsigned char, ZC_MEMO_SIZE> 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;
}

View File

@ -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 <unordered_map>
#include <tuple>
#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<std::string, CAmount, std::string> SendManyRecipient;
@ -50,7 +50,7 @@ struct WitnessAnchorData {
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
public:
AsyncRPCOperation_sendmany(std::string fromAddress, std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, Value contextInfo = Value::null);
AsyncRPCOperation_sendmany(std::string fromAddress, std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> 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<JSOutPoint> & );
UniValue perform_joinsplit(AsyncJoinSplitInfo &, std::vector<JSOutPoint> & );
// JoinSplit where you have the witnesses and anchor
Object perform_joinsplit(
UniValue perform_joinsplit(
AsyncJoinSplitInfo & info,
std::vector<boost::optional < ZCIncrementalWitness>> 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<JSOutPoint> &v ) {
UniValue perform_joinsplit(AsyncJoinSplitInfo &info, std::vector<JSOutPoint> &v ) {
return delegate->perform_joinsplit(info, v);
}
Object perform_joinsplit(
UniValue perform_joinsplit(
AsyncJoinSplitInfo & info,
std::vector<boost::optional < ZCIncrementalWitness>> 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);
}

View File

@ -19,16 +19,15 @@
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "json/json_spirit_value.h"
#include "univalue/univalue.h"
using namespace json_spirit;
using namespace std;
void EnsureWalletIsUnlocked();
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(

File diff suppressed because it is too large Load Diff