Merge pull request #6121

44c7474 univalue: add type check unit tests (Jonas Schnelli)
c023092 univalue: add strict type checking (Wladimir J. van der Laan)
7e98a3c util: Add ParseInt64 and ParseDouble functions (Wladimir J. van der Laan)
043df2b Simplify RPCclient, adapt json_parse_error test (Wladimir J. van der Laan)
519eede fix univalue json parse tests (Jonas Schnelli)
c7fbbc7 fix missing univalue types during constructing (Jonas Schnelli)
8f7e4ab fix rpc batching univalue issue (Jonas Schnelli)
9a8897f Remove JSON Spirit wrapper, remove JSON Spirit leftovers (Jonas Schnelli)
3df0411 remove JSON Spirit UniValue wrapper (Jonas Schnelli)
1f263c8 fix rpc unit test, plain numbers are not JSON compatible object (Jonas Schnelli)
e04d9c2 univalue: correct bool support (Jonas Schnelli)
0c5b2cf univalue: add support for real, fix percision and make it json_spirit compatible (Jonas Schnelli)
21c10de special threatment for null,true,false because they are non valid json (Jonas Schnelli)
6c7bee0 expicit set UniValue type to avoid empty values (Jonas Schnelli)
53b4671 extend conversion to UniValue (Jonas Schnelli)
15982a8 Convert tree to using univalue. Eliminate all json_spirit uses. (Jeff Garzik)
5e3060c UniValue: export NullUniValue global constant (Jeff Garzik)
efc7883 UniValue: prefer .size() to .count(), to harmonize w/ existing tree (Jeff Garzik)
This commit is contained in:
Wladimir J. van der Laan 2015-06-04 18:41:21 +02:00
commit 466f0ea0e6
No known key found for this signature in database
GPG key ID: 74810B012346C9A6
44 changed files with 1127 additions and 2740 deletions

View file

@ -154,17 +154,6 @@ BITCOIN_CORE_H = \
wallet/wallet_ismine.h \
wallet/walletdb.h
JSON_H = \
json/json_spirit.h \
json/json_spirit_error_position.h \
json/json_spirit_reader.h \
json/json_spirit_reader_template.h \
json/json_spirit_stream_reader.h \
json/json_spirit_utils.h \
json/json_spirit_value.h \
json/json_spirit_writer.h \
json/json_spirit_writer_template.h
obj/build.h: FORCE
@$(MKDIR_P) $(builddir)/obj
@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
@ -200,7 +189,6 @@ libbitcoin_server_a_SOURCES = \
txdb.cpp \
txmempool.cpp \
validationinterface.cpp \
$(JSON_H) \
$(BITCOIN_CORE_H)
# wallet: shared between bitcoind and bitcoin-qt, but only linked
@ -342,6 +330,7 @@ endif
bitcoin_cli_LDADD = \
$(LIBBITCOIN_CLI) \
$(LIBBITCOIN_UNIVALUE) \
$(LIBBITCOIN_UTIL) \
$(LIBSECP256K1)

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()
{
@ -94,7 +95,7 @@ static bool AppInitRPC(int argc, char* argv[])
return true;
}
Object CallRPC(const string& strMethod, const Array& params)
UniValue CallRPC(const string& strMethod, const UniValue& params)
{
if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
throw runtime_error(strprintf(
@ -142,10 +143,10 @@ Object CallRPC(const string& strMethod, const Array& params)
throw runtime_error("no response from server");
// Parse reply
Value valReply;
if (!read_string(strReply, valReply))
UniValue valReply(UniValue::VSTR);
if (!valReply.read(strReply))
throw runtime_error("couldn't parse reply from server");
const Object& reply = valReply.get_obj();
const UniValue& reply = valReply.get_obj();
if (reply.empty())
throw runtime_error("expected reply to have result, error and id properties");
@ -170,35 +171,34 @@ int CommandLineRPC(int argc, char *argv[])
// Parameters default to strings
std::vector<std::string> strParams(&argv[2], &argv[argc]);
Array params = RPCConvertValues(strMethod, strParams);
UniValue params = RPCConvertValues(strMethod, strParams);
// Execute and handle connection failures with -rpcwait
const bool fWait = GetBoolArg("-rpcwait", false);
do {
try {
const Object reply = CallRPC(strMethod, params);
const UniValue reply = CallRPC(strMethod, params);
// Parse reply
const Value& result = find_value(reply, "result");
const Value& error = find_value(reply, "error");
const UniValue& result = find_value(reply, "result");
const UniValue& error = find_value(reply, "error");
if (error.type() != null_type) {
if (!error.isNull()) {
// Error
const int code = find_value(error.get_obj(), "code").get_int();
int code = error["code"].get_int();
if (fWait && code == RPC_IN_WARMUP)
throw CConnectionFailed("server in warmup");
strPrint = "error: " + write_string(error, false);
strPrint = "error: " + error.write();
nRet = abs(code);
} else {
// Result
if (result.type() == null_type)
if (result.isNull())
strPrint = "";
else if (result.type() == str_type)
else if (result.isStr())
strPrint = result.get_str();
else
strPrint = write_string(result, true);
strPrint = result.write(2);
}
// Connection succeeded, no need to retry.
break;
}

View file

@ -346,7 +346,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
UniValue keysObj = registers["privatekeys"];
fGivenKeys = true;
for (unsigned int kidx = 0; kidx < keysObj.count(); kidx++) {
for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
if (!keysObj[kidx].isStr())
throw runtime_error("privatekey not a string");
CBitcoinSecret vchSecret;
@ -363,7 +363,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
throw runtime_error("prevtxs register variable must be set.");
UniValue prevtxsObj = registers["prevtxs"];
{
for (unsigned int previdx = 0; previdx < prevtxsObj.count(); previdx++) {
for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) {
UniValue prevOut = prevtxsObj[previdx];
if (!prevOut.isObject())
throw runtime_error("expected prevtxs internal object");

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

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 GetDifficulty(const CBlockIndex* blockindex)
{
@ -53,9 +52,9 @@ double GetDifficulty(const CBlockIndex* blockindex)
}
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
{
Object result;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hash", block.GetHash().GetHex()));
int confirmations = -1;
// Only report confirmations if the block is on the main chain
@ -66,12 +65,12 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDe
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
Array txs;
UniValue txs(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
{
if(txDetails)
{
Object objTx;
UniValue objTx(UniValue::VOBJ);
TxToJSON(tx, uint256(), objTx);
txs.push_back(objTx);
}
@ -94,7 +93,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDe
}
Value getblockcount(const Array& params, bool fHelp)
UniValue getblockcount(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -111,7 +110,7 @@ Value getblockcount(const Array& params, bool fHelp)
return chainActive.Height();
}
Value getbestblockhash(const Array& params, bool fHelp)
UniValue getbestblockhash(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -128,7 +127,7 @@ Value getbestblockhash(const Array& params, bool fHelp)
return chainActive.Tip()->GetBlockHash().GetHex();
}
Value getdifficulty(const Array& params, bool fHelp)
UniValue getdifficulty(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -146,7 +145,7 @@ Value getdifficulty(const Array& params, bool fHelp)
}
Value getrawmempool(const Array& params, bool fHelp)
UniValue getrawmempool(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
@ -187,12 +186,12 @@ Value getrawmempool(const Array& params, bool fHelp)
if (fVerbose)
{
LOCK(mempool.cs);
Object o;
UniValue o(UniValue::VOBJ);
BOOST_FOREACH(const PAIRTYPE(uint256, CTxMemPoolEntry)& entry, mempool.mapTx)
{
const uint256& hash = entry.first;
const CTxMemPoolEntry& e = entry.second;
Object info;
UniValue info(UniValue::VOBJ);
info.push_back(Pair("size", (int)e.GetTxSize()));
info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
info.push_back(Pair("time", e.GetTime()));
@ -206,7 +205,13 @@ Value getrawmempool(const Array& params, bool fHelp)
if (mempool.exists(txin.prevout.hash))
setDepends.insert(txin.prevout.hash.ToString());
}
Array depends(setDepends.begin(), setDepends.end());
UniValue depends(UniValue::VARR);
BOOST_FOREACH(const string& dep, setDepends)
{
depends.push_back(dep);
}
info.push_back(Pair("depends", depends));
o.push_back(Pair(hash.ToString(), info));
}
@ -217,7 +222,7 @@ Value getrawmempool(const Array& params, bool fHelp)
vector<uint256> vtxid;
mempool.queryHashes(vtxid);
Array a;
UniValue a(UniValue::VARR);
BOOST_FOREACH(const uint256& hash, vtxid)
a.push_back(hash.ToString());
@ -225,7 +230,7 @@ Value getrawmempool(const Array& params, bool fHelp)
}
}
Value getblockhash(const Array& params, bool fHelp)
UniValue getblockhash(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -250,7 +255,7 @@ Value getblockhash(const Array& params, bool fHelp)
return pblockindex->GetBlockHash().GetHex();
}
Value getblock(const Array& params, bool fHelp)
UniValue getblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -318,7 +323,7 @@ Value getblock(const Array& params, bool fHelp)
return blockToJSON(block, pblockindex);
}
Value gettxoutsetinfo(const Array& params, bool fHelp)
UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -342,7 +347,7 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
LOCK(cs_main);
Object ret;
UniValue ret(UniValue::VOBJ);
CCoinsStats stats;
FlushStateToDisk();
@ -358,7 +363,7 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
return ret;
}
Value gettxout(const Array& params, bool fHelp)
UniValue gettxout(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 3)
throw runtime_error(
@ -398,7 +403,7 @@ Value gettxout(const Array& params, bool fHelp)
LOCK(cs_main);
Object ret;
UniValue ret(UniValue::VOBJ);
std::string strHash = params[0].get_str();
uint256 hash(uint256S(strHash));
@ -412,14 +417,14 @@ Value gettxout(const Array& params, bool fHelp)
LOCK(mempool.cs);
CCoinsViewMemPool view(pcoinsTip, mempool);
if (!view.GetCoins(hash, coins))
return Value::null;
return NullUniValue;
mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
} else {
if (!pcoinsTip->GetCoins(hash, coins))
return Value::null;
return NullUniValue;
}
if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
return Value::null;
return NullUniValue;
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
CBlockIndex *pindex = it->second;
@ -429,7 +434,7 @@ Value gettxout(const Array& params, bool fHelp)
else
ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
Object o;
UniValue o(UniValue::VOBJ);
ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
ret.push_back(Pair("scriptPubKey", o));
ret.push_back(Pair("version", coins.nVersion));
@ -438,7 +443,7 @@ Value gettxout(const Array& params, bool fHelp)
return ret;
}
Value verifychain(const Array& params, bool fHelp)
UniValue verifychain(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
throw runtime_error(
@ -466,7 +471,7 @@ Value verifychain(const Array& params, bool fHelp)
return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
}
Value getblockchaininfo(const Array& params, bool fHelp)
UniValue getblockchaininfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -489,7 +494,7 @@ Value getblockchaininfo(const Array& params, bool fHelp)
LOCK(cs_main);
Object obj;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("chain", Params().NetworkIDString()));
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
@ -524,7 +529,7 @@ struct CompareBlocksByHeight
}
};
Value getchaintips(const Array& params, bool fHelp)
UniValue getchaintips(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -576,10 +581,10 @@ Value getchaintips(const Array& params, bool fHelp)
setTips.insert(chainActive.Tip());
/* Construct the output array. */
Array res;
UniValue res(UniValue::VARR);
BOOST_FOREACH(const CBlockIndex* block, setTips)
{
Object obj;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("height", block->nHeight));
obj.push_back(Pair("hash", block->phashBlock->GetHex()));
@ -614,7 +619,7 @@ Value getchaintips(const Array& params, bool fHelp)
return res;
}
Value getmempoolinfo(const Array& params, bool fHelp)
UniValue getmempoolinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -630,14 +635,14 @@ Value getmempoolinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getmempoolinfo", "")
);
Object ret;
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("size", (int64_t) mempool.size()));
ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
return ret;
}
Value invalidateblock(const Array& params, bool fHelp)
UniValue invalidateblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -672,10 +677,10 @@ Value invalidateblock(const Array& params, bool fHelp)
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
}
return Value::null;
return NullUniValue;
}
Value reconsiderblock(const Array& params, bool fHelp)
UniValue reconsiderblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -711,5 +716,5 @@ Value reconsiderblock(const Array& params, bool fHelp)
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
}
return Value::null;
return NullUniValue;
}

View file

@ -11,8 +11,10 @@
#include <set>
#include <stdint.h>
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
#include "univalue/univalue.h"
using namespace std;
using namespace json_spirit;
class CRPCConvertParam
{
@ -119,25 +121,32 @@ CRPCConvertTable::CRPCConvertTable()
static CRPCConvertTable rpcCvtTable;
/** 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

@ -24,10 +24,8 @@
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include "univalue/univalue.h"
using namespace json_spirit;
using namespace std;
/**
@ -35,7 +33,7 @@ using namespace std;
* or from the last difficulty change if 'lookup' is nonpositive.
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
*/
Value GetNetworkHashPS(int lookup, int height) {
UniValue GetNetworkHashPS(int lookup, int height) {
CBlockIndex *pb = chainActive.Tip();
if (height >= 0 && height < chainActive.Height())
@ -72,7 +70,7 @@ Value GetNetworkHashPS(int lookup, int height) {
return (int64_t)(workDiff.getdouble() / timeDiff);
}
Value getnetworkhashps(const Array& params, bool fHelp)
UniValue getnetworkhashps(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
throw runtime_error(
@ -95,7 +93,7 @@ Value getnetworkhashps(const Array& params, bool fHelp)
}
#ifdef ENABLE_WALLET
Value getgenerate(const Array& params, bool fHelp)
UniValue getgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -114,7 +112,7 @@ Value getgenerate(const Array& params, bool fHelp)
return GetBoolArg("-gen", false);
}
Value generate(const Array& params, bool fHelp)
UniValue generate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 1)
throw runtime_error(
@ -147,7 +145,7 @@ Value generate(const Array& params, bool fHelp)
nHeightEnd = nHeightStart+nGenerate;
}
unsigned int nExtraNonce = 0;
Array blockHashes;
UniValue blockHashes(UniValue::VARR);
while (nHeight < nHeightEnd)
{
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
@ -173,7 +171,7 @@ Value generate(const Array& params, bool fHelp)
}
Value setgenerate(const Array& params, bool fHelp)
UniValue setgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -216,12 +214,12 @@ Value setgenerate(const Array& params, bool fHelp)
mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
return Value::null;
return NullUniValue;
}
#endif
Value getmininginfo(const Array& params, bool fHelp)
UniValue getmininginfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -248,7 +246,7 @@ Value getmininginfo(const Array& params, bool fHelp)
LOCK(cs_main);
Object obj;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
@ -267,7 +265,7 @@ Value getmininginfo(const Array& params, bool fHelp)
// NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
Value prioritisetransaction(const Array& params, bool fHelp)
UniValue prioritisetransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
throw runtime_error(
@ -299,10 +297,10 @@ Value prioritisetransaction(const Array& params, bool fHelp)
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
static Value BIP22ValidationResult(const CValidationState& state)
static UniValue BIP22ValidationResult(const CValidationState& state)
{
if (state.IsValid())
return Value::null;
return NullUniValue;
std::string strRejectReason = state.GetRejectReason();
if (state.IsError())
@ -317,7 +315,7 @@ static Value BIP22ValidationResult(const CValidationState& state)
return "valid?";
}
Value getblocktemplate(const Array& params, bool fHelp)
UniValue getblocktemplate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
@ -382,14 +380,14 @@ Value getblocktemplate(const Array& params, bool fHelp)
LOCK(cs_main);
std::string strMode = "template";
Value lpval = Value::null;
UniValue lpval = NullUniValue;
if (params.size() > 0)
{
const Object& oparam = params[0].get_obj();
const Value& modeval = find_value(oparam, "mode");
if (modeval.type() == str_type)
const UniValue& oparam = params[0].get_obj();
const UniValue& modeval = find_value(oparam, "mode");
if (modeval.isStr())
strMode = modeval.get_str();
else if (modeval.type() == null_type)
else if (modeval.isNull())
{
/* Do nothing */
}
@ -399,8 +397,8 @@ Value getblocktemplate(const Array& params, bool fHelp)
if (strMode == "proposal")
{
const Value& dataval = find_value(oparam, "data");
if (dataval.type() != str_type)
const UniValue& dataval = find_value(oparam, "data");
if (dataval.isStr())
throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
CBlock block;
@ -439,14 +437,14 @@ Value getblocktemplate(const Array& params, bool fHelp)
static unsigned int nTransactionsUpdatedLast;
if (lpval.type() != null_type)
if (!lpval.isNull())
{
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
uint256 hashWatchedChain;
boost::system_time checktxtime;
unsigned int nTransactionsUpdatedLastLP;
if (lpval.type() == str_type)
if (lpval.isStr())
{
// Format: <hashBestChain><nTransactionsUpdatedLast>
std::string lpstr = lpval.get_str();
@ -520,9 +518,9 @@ Value getblocktemplate(const Array& params, bool fHelp)
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nNonce = 0;
static const Array aCaps = boost::assign::list_of("proposal");
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
Array transactions;
UniValue transactions(UniValue::VARR);
map<uint256, int64_t> setTxIndex;
int i = 0;
BOOST_FOREACH (CTransaction& tx, pblock->vtx)
@ -533,13 +531,13 @@ Value getblocktemplate(const Array& params, bool fHelp)
if (tx.IsCoinBase())
continue;
Object entry;
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("data", EncodeHexTx(tx)));
entry.push_back(Pair("hash", txHash.GetHex()));
Array deps;
UniValue deps(UniValue::VARR);
BOOST_FOREACH (const CTxIn &in, tx.vin)
{
if (setTxIndex.count(in.prevout.hash))
@ -554,12 +552,12 @@ Value getblocktemplate(const Array& params, bool fHelp)
transactions.push_back(entry);
}
Object aux;
UniValue aux(UniValue::VOBJ);
aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
static Array aMutable;
static UniValue aMutable(UniValue::VARR);
if (aMutable.empty())
{
aMutable.push_back("time");
@ -567,7 +565,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
aMutable.push_back("prevblock");
}
Object result;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("capabilities", aCaps));
result.push_back(Pair("version", pblock->nVersion));
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
@ -606,7 +604,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(
@ -667,7 +665,7 @@ Value submitblock(const Array& params, bool fHelp)
return BIP22ValidationResult(state);
}
Value estimatefee(const Array& params, bool fHelp)
UniValue estimatefee(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -686,7 +684,7 @@ Value estimatefee(const Array& params, bool fHelp)
+ HelpExampleCli("estimatefee", "6")
);
RPCTypeCheck(params, boost::assign::list_of(int_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
int nBlocks = params[0].get_int();
if (nBlocks < 1)
@ -699,7 +697,7 @@ Value estimatefee(const Array& params, bool fHelp)
return ValueFromAmount(feeRate.GetFeePerK());
}
Value estimatepriority(const Array& params, bool fHelp)
UniValue estimatepriority(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -718,7 +716,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)

View file

@ -20,10 +20,9 @@
#include <stdint.h>
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
using namespace json_spirit;
#include "univalue/univalue.h"
using namespace std;
/**
@ -39,7 +38,7 @@ using namespace std;
*
* Or alternatively, create a specific query method for the information.
**/
Value getinfo(const Array& params, bool fHelp)
UniValue getinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@ -78,7 +77,7 @@ Value getinfo(const Array& params, bool fHelp)
proxyType proxy;
GetProxy(NET_IPV4, proxy);
Object obj;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
#ifdef ENABLE_WALLET
@ -108,7 +107,7 @@ Value getinfo(const Array& params, bool fHelp)
}
#ifdef ENABLE_WALLET
class DescribeAddressVisitor : public boost::static_visitor<Object>
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
{
private:
isminetype mine;
@ -116,10 +115,10 @@ private:
public:
DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
Object operator()(const CNoDestination &dest) const { return Object(); }
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
Object operator()(const CKeyID &keyID) const {
Object obj;
UniValue operator()(const CKeyID &keyID) const {
UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey;
obj.push_back(Pair("isscript", false));
if (mine == ISMINE_SPENDABLE) {
@ -130,8 +129,8 @@ public:
return obj;
}
Object operator()(const CScriptID &scriptID) const {
Object obj;
UniValue operator()(const CScriptID &scriptID) const {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("isscript", true));
if (mine != ISMINE_NO) {
CScript subscript;
@ -142,7 +141,7 @@ public:
ExtractDestinations(subscript, whichType, addresses, nRequired);
obj.push_back(Pair("script", GetTxnOutputType(whichType)));
obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
Array a;
UniValue a(UniValue::VARR);
BOOST_FOREACH(const CTxDestination& addr, addresses)
a.push_back(CBitcoinAddress(addr).ToString());
obj.push_back(Pair("addresses", a));
@ -154,7 +153,7 @@ public:
};
#endif
Value validateaddress(const Array& params, bool fHelp)
UniValue validateaddress(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -187,7 +186,7 @@ Value validateaddress(const Array& params, bool fHelp)
CBitcoinAddress address(params[0].get_str());
bool isValid = address.IsValid();
Object ret;
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("isvalid", isValid));
if (isValid)
{
@ -203,8 +202,8 @@ Value validateaddress(const Array& params, bool fHelp)
ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
if (mine != ISMINE_NO) {
ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
ret.insert(ret.end(), detail.begin(), detail.end());
UniValue detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
ret.pushKVs(detail);
}
if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
@ -216,10 +215,10 @@ Value validateaddress(const Array& params, bool fHelp)
/**
* Used by addmultisigaddress / createmultisig:
*/
CScript _createmultisig_redeemScript(const Array& params)
CScript _createmultisig_redeemScript(const UniValue& params)
{
int nRequired = params[0].get_int();
const Array& keys = params[1].get_array();
const UniValue& keys = params[1].get_array();
// Gather public keys
if (nRequired < 1)
@ -277,7 +276,7 @@ CScript _createmultisig_redeemScript(const Array& params)
return result;
}
Value createmultisig(const Array& params, bool fHelp)
UniValue createmultisig(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 2)
{
@ -313,14 +312,14 @@ Value createmultisig(const Array& params, bool fHelp)
CScriptID innerID(inner);
CBitcoinAddress address(innerID);
Object result;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("address", address.ToString()));
result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
return result;
}
Value verifymessage(const Array& params, bool fHelp)
UniValue verifymessage(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
throw runtime_error(
@ -374,7 +373,7 @@ Value verifymessage(const Array& params, bool fHelp)
return (pubkey.GetID() == keyID);
}
Value setmocktime(const Array& params, bool fHelp)
UniValue setmocktime(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -390,8 +389,8 @@ Value setmocktime(const Array& params, bool fHelp)
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(int_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
SetMockTime(params[0].get_int64());
return Value::null;
return NullUniValue;
}

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

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

View file

@ -15,9 +15,7 @@
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
//! HTTP status codes
enum HTTPStatusCode
@ -160,9 +158,9 @@ int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto);
int ReadHTTPHeaders(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet);
int ReadHTTPMessage(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet,
std::string& strMessageRet, int nProto, size_t max_size);
std::string JSONRPCRequest(const std::string& strMethod, const json_spirit::Array& params, const json_spirit::Value& id);
json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
json_spirit::Object JSONRPCError(int code, const std::string& message);
std::string JSONRPCRequest(const std::string& strMethod, const UniValue& params, const UniValue& id);
UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id);
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
UniValue JSONRPCError(int code, const std::string& message);
#endif // BITCOIN_RPCPROTOCOL_H

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,26 +48,26 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeH
out.push_back(Pair("reqSigs", nRequired));
out.push_back(Pair("type", GetTxnOutputType(type)));
Array a;
UniValue a(UniValue::VARR);
BOOST_FOREACH(const CTxDestination& addr, addresses)
a.push_back(CBitcoinAddress(addr).ToString());
out.push_back(Pair("addresses", a));
}
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
entry.push_back(Pair("txid", tx.GetHash().GetHex()));
entry.push_back(Pair("version", tx.nVersion));
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
Array vin;
UniValue vin(UniValue::VARR);
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
Object in;
UniValue in(UniValue::VOBJ);
if (tx.IsCoinBase())
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
else {
in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
in.push_back(Pair("vout", (int64_t)txin.prevout.n));
Object o;
UniValue o(UniValue::VOBJ);
o.push_back(Pair("asm", txin.scriptSig.ToString()));
o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
in.push_back(Pair("scriptSig", o));
@ -77,13 +76,13 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
vin.push_back(in);
}
entry.push_back(Pair("vin", vin));
Array vout;
UniValue vout(UniValue::VARR);
for (unsigned int i = 0; i < tx.vout.size(); i++) {
const CTxOut& txout = tx.vout[i];
Object out;
UniValue out(UniValue::VOBJ);
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
out.push_back(Pair("n", (int64_t)i));
Object o;
UniValue o(UniValue::VOBJ);
ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
out.push_back(Pair("scriptPubKey", o));
vout.push_back(out);
@ -106,7 +105,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
}
}
Value getrawtransaction(const Array& params, bool fHelp)
UniValue getrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -190,13 +189,13 @@ Value getrawtransaction(const Array& params, bool fHelp)
if (!fVerbose)
return strHex;
Object result;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", strHex));
TxToJSON(tx, hashBlock, result);
return result;
}
Value gettxoutproof(const Array& params, bool fHelp)
UniValue gettxoutproof(const UniValue& params, bool fHelp)
{
if (fHelp || (params.size() != 1 && params.size() != 2))
throw runtime_error(
@ -220,8 +219,9 @@ Value gettxoutproof(const Array& params, bool fHelp)
set<uint256> setTxids;
uint256 oneTxid;
Array txids = params[0].get_array();
BOOST_FOREACH(Value& txid, txids) {
UniValue txids = params[0].get_array();
for (unsigned int idx = 0; idx < txids.size(); idx++) {
const UniValue& txid = txids[idx];
if (txid.get_str().length() != 64 || !IsHex(txid.get_str()))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid txid ")+txid.get_str());
uint256 hash(uint256S(txid.get_str()));
@ -276,7 +276,7 @@ Value gettxoutproof(const Array& params, bool fHelp)
return strHex;
}
Value verifytxoutproof(const Array& params, bool fHelp)
UniValue verifytxoutproof(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -293,7 +293,7 @@ Value verifytxoutproof(const Array& params, bool fHelp)
CMerkleBlock merkleBlock;
ssMB >> merkleBlock;
Array res;
UniValue res(UniValue::VARR);
vector<uint256> vMatch;
if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot)
@ -309,7 +309,7 @@ Value verifytxoutproof(const Array& params, bool fHelp)
return res;
}
Value createrawtransaction(const Array& params, bool fHelp)
UniValue createrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 2)
throw runtime_error(
@ -343,20 +343,21 @@ Value createrawtransaction(const Array& params, bool fHelp)
);
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ));
Array inputs = params[0].get_array();
Object sendTo = params[1].get_obj();
UniValue inputs = params[0].get_array();
UniValue sendTo = params[1].get_obj();
CMutableTransaction rawTx;
BOOST_FOREACH(const Value& input, inputs) {
const Object& o = input.get_obj();
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
const UniValue& o = input.get_obj();
uint256 txid = ParseHashO(o, "txid");
const Value& vout_v = find_value(o, "vout");
if (vout_v.type() != int_type)
const UniValue& vout_v = find_value(o, "vout");
if (!vout_v.isNum())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
int nOutput = vout_v.get_int();
if (nOutput < 0)
@ -367,17 +368,18 @@ Value createrawtransaction(const Array& params, bool fHelp)
}
set<CBitcoinAddress> setAddress;
BOOST_FOREACH(const Pair& s, sendTo) {
CBitcoinAddress address(s.name_);
vector<string> addrList = sendTo.getKeys();
BOOST_FOREACH(const string& name_, addrList) {
CBitcoinAddress address(name_);
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
if (setAddress.count(address))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
setAddress.insert(address);
CScript scriptPubKey = GetScriptForDestination(address.Get());
CAmount nAmount = AmountFromValue(s.value_);
CAmount nAmount = AmountFromValue(sendTo[name_]);
CTxOut out(nAmount, scriptPubKey);
rawTx.vout.push_back(out);
@ -386,7 +388,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
return EncodeHexTx(rawTx);
}
Value decoderawtransaction(const Array& params, bool fHelp)
UniValue decoderawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -438,20 +440,20 @@ Value decoderawtransaction(const Array& params, bool fHelp)
);
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
CTransaction tx;
if (!DecodeHexTx(tx, params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
Object result;
UniValue result(UniValue::VOBJ);
TxToJSON(tx, uint256(), result);
return result;
}
Value decodescript(const Array& params, bool fHelp)
UniValue decodescript(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@ -477,9 +479,9 @@ Value decodescript(const Array& params, bool fHelp)
);
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
Object r;
UniValue r(UniValue::VOBJ);
CScript script;
if (params[0].get_str().size() > 0){
vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
@ -494,9 +496,9 @@ Value decodescript(const Array& params, bool fHelp)
}
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
static void TxInErrorToJSON(const CTxIn& txin, Array& vErrorsRet, const std::string& strMessage)
static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
{
Object entry;
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("txid", txin.prevout.hash.ToString()));
entry.push_back(Pair("vout", (uint64_t)txin.prevout.n));
entry.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
@ -505,7 +507,7 @@ static void TxInErrorToJSON(const CTxIn& txin, Array& vErrorsRet, const std::str
vErrorsRet.push_back(entry);
}
Value signrawtransaction(const Array& params, bool fHelp)
UniValue signrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 4)
throw runtime_error(
@ -570,7 +572,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
#else
LOCK(cs_main);
#endif
RPCTypeCheck(params, boost::assign::list_of(str_type)(array_type)(array_type)(str_type), true);
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true);
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
@ -613,10 +615,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fGivenKeys = false;
CBasicKeyStore tempKeystore;
if (params.size() > 2 && params[2].type() != null_type) {
if (params.size() > 2 && !params[2].isNull()) {
fGivenKeys = true;
Array keys = params[2].get_array();
BOOST_FOREACH(Value k, keys) {
UniValue keys = params[2].get_array();
for (unsigned int idx = 0; idx < keys.size(); idx++) {
UniValue k = keys[idx];
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(k.get_str());
if (!fGood)
@ -633,15 +636,16 @@ Value signrawtransaction(const Array& params, bool fHelp)
#endif
// Add previous txouts given in the RPC call:
if (params.size() > 1 && params[1].type() != null_type) {
Array prevTxs = params[1].get_array();
BOOST_FOREACH(Value& p, prevTxs) {
if (p.type() != obj_type)
if (params.size() > 1 && !params[1].isNull()) {
UniValue prevTxs = params[1].get_array();
for (unsigned int idx = 0; idx < prevTxs.size(); idx++) {
const UniValue& p = prevTxs[idx];
if (!p.isObject())
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
Object prevOut = p.get_obj();
UniValue prevOut = p.get_obj();
RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
RPCTypeCheckObj(prevOut, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)("scriptPubKey", UniValue::VSTR));
uint256 txid = ParseHashO(prevOut, "txid");
@ -669,9 +673,9 @@ Value signrawtransaction(const Array& params, bool fHelp)
// if redeemScript given and not using the local wallet (private keys
// given), add redeemScript to the tempKeystore so it can be signed:
if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
Value v = find_value(prevOut, "redeemScript");
if (!(v == Value::null)) {
RPCTypeCheckObj(prevOut, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)("scriptPubKey", UniValue::VSTR)("redeemScript",UniValue::VSTR));
UniValue v = find_value(prevOut, "redeemScript");
if (!v.isNull()) {
vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
CScript redeemScript(rsData.begin(), rsData.end());
tempKeystore.AddCScript(redeemScript);
@ -687,7 +691,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
#endif
int nHashType = SIGHASH_ALL;
if (params.size() > 3 && params[3].type() != null_type) {
if (params.size() > 3 && !params[3].isNull()) {
static map<string, int> mapSigHashValues =
boost::assign::map_list_of
(string("ALL"), int(SIGHASH_ALL))
@ -707,7 +711,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Script verification errors
Array vErrors;
UniValue vErrors(UniValue::VARR);
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
@ -735,7 +739,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
}
bool fComplete = vErrors.empty();
Object result;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
result.push_back(Pair("complete", fComplete));
if (!vErrors.empty()) {
@ -745,7 +749,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
return result;
}
Value sendrawtransaction(const Array& params, bool fHelp)
UniValue sendrawtransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -769,7 +773,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
);
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
// parse hex string from parameter
CTransaction tx;

View file

@ -27,10 +27,10 @@
#include <boost/shared_ptr.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/thread.hpp>
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
using namespace boost::asio;
using namespace json_spirit;
using namespace RPCServer;
using namespace std;
@ -78,41 +78,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)
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);
}
}
@ -123,7 +123,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)
@ -134,15 +134,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+"')");
@ -150,20 +150,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);
}
@ -195,7 +195,7 @@ string CRPCTable::help(string strCommand) const
continue;
try
{
Array params;
UniValue params;
rpcfn_type pfn = pcmd->actor;
if (setDone.insert(pfn).second)
(*pfn)(params, true);
@ -228,7 +228,7 @@ string CRPCTable::help(string strCommand) const
return strRet;
}
Value help(const Array& params, bool fHelp)
UniValue help(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
@ -248,7 +248,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)
@ -410,14 +410,14 @@ bool HTTPAuthorized(map<string, string>& mapHeaders)
return TimingResistantEqual(strUserPass, strRPCUserColonPass);
}
void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
void ErrorReply(std::ostream& stream, const UniValue& objError, const UniValue& id)
{
// Send error reply from json-rpc error object
int nStatus = HTTP_INTERNAL_SERVER_ERROR;
int code = find_value(objError, "code").get_int();
if (code == RPC_INVALID_REQUEST) nStatus = HTTP_BAD_REQUEST;
else if (code == RPC_METHOD_NOT_FOUND) nStatus = HTTP_NOT_FOUND;
string strReply = JSONRPCReply(Value::null, objError, id);
string strReply = JSONRPCReply(NullUniValue, objError, id);
stream << HTTPReply(nStatus, strReply, false) << std::flush;
}
@ -824,76 +824,76 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
class JSONRequest
{
public:
Value id;
UniValue id;
string strMethod;
Array params;
UniValue params;
JSONRequest() { id = Value::null; }
void parse(const Value& valRequest);
JSONRequest() { id = NullUniValue; }
void parse(const UniValue& valRequest);
};
void JSONRequest::parse(const Value& valRequest)
void JSONRequest::parse(const UniValue& valRequest)
{
// Parse request
if (valRequest.type() != obj_type)
if (!valRequest.isObject())
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
const Object& request = valRequest.get_obj();
const UniValue& request = valRequest.get_obj();
// Parse id now so errors from here on will have the id
id = find_value(request, "id");
// Parse method
Value valMethod = find_value(request, "method");
if (valMethod.type() == null_type)
UniValue valMethod = find_value(request, "method");
if (valMethod.isNull())
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
if (valMethod.type() != str_type)
if (!valMethod.isStr())
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getblocktemplate")
LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
// Parse params
Value valParams = find_value(request, "params");
if (valParams.type() == array_type)
UniValue valParams = find_value(request, "params");
if (valParams.isArray())
params = valParams.get_array();
else if (valParams.type() == null_type)
params = Array();
else if (valParams.isNull())
params = UniValue(UniValue::VARR);
else
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array");
}
static Object JSONRPCExecOne(const Value& req)
static UniValue JSONRPCExecOne(const UniValue& req)
{
Object rpc_result;
UniValue rpc_result(UniValue::VOBJ);
JSONRequest jreq;
try {
jreq.parse(req);
Value result = tableRPC.execute(jreq.strMethod, jreq.params);
rpc_result = JSONRPCReplyObj(result, Value::null, jreq.id);
UniValue result = tableRPC.execute(jreq.strMethod, jreq.params);
rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
}
catch (const Object& objError)
catch (const UniValue& objError)
{
rpc_result = JSONRPCReplyObj(Value::null, objError, jreq.id);
rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
}
catch (const std::exception& e)
{
rpc_result = JSONRPCReplyObj(Value::null,
rpc_result = JSONRPCReplyObj(NullUniValue,
JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
}
return rpc_result;
}
static string JSONRPCExecBatch(const Array& vReq)
static string JSONRPCExecBatch(const UniValue& vReq)
{
Array ret;
UniValue ret(UniValue::VARR);
for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
return write_string(Value(ret), false) + "\n";
return ret.write() + "\n";
}
static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
@ -924,8 +924,8 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
try
{
// Parse request
Value valRequest;
if (!read_string(strRequest, valRequest))
UniValue valRequest;
if (!valRequest.read(strRequest))
throw JSONRPCError(RPC_PARSE_ERROR, "Parse error");
// Return immediately if in warmup
@ -938,23 +938,23 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
string strReply;
// singleton request
if (valRequest.type() == obj_type) {
if (valRequest.isObject()) {
jreq.parse(valRequest);
Value result = tableRPC.execute(jreq.strMethod, jreq.params);
UniValue result = tableRPC.execute(jreq.strMethod, jreq.params);
// Send reply
strReply = JSONRPCReply(result, Value::null, jreq.id);
strReply = JSONRPCReply(result, NullUniValue, jreq.id);
// array of requests
} else if (valRequest.type() == array_type)
} else if (valRequest.isArray())
strReply = JSONRPCExecBatch(valRequest.get_array());
else
throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error");
conn->stream() << HTTPReplyHeader(HTTP_OK, fRun, strReply.size()) << strReply << std::flush;
}
catch (const Object& objError)
catch (const UniValue& objError)
{
ErrorReply(conn->stream(), objError, jreq.id);
return false;
@ -1004,7 +1004,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

@ -15,9 +15,9 @@
#include <stdint.h>
#include <string>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
#include <boost/function.hpp>
#include "univalue/univalue.h"
class CRPCCommand;
@ -71,14 +71,15 @@ bool RPCIsInWarmup(std::string *statusOut);
* the right number of arguments are passed, just that any passed are the correct type.
* Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type));
*/
void RPCTypeCheck(const json_spirit::Array& params,
const std::list<json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
/**
* Check for expected keys/value types in an Object.
* Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type));
*/
void RPCTypeCheck(const json_spirit::Object& o,
const std::map<std::string, json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
void RPCTypeCheck(const UniValue& params,
const std::list<UniValue::VType>& typesExpected, bool fAllowNull=false);
/*
Check for expected keys/value types in an Object.
Use like: RPCTypeCheckObj(object, boost::assign::map_list_of("name", str_type)("value", int_type));
*/
void RPCTypeCheckObj(const UniValue& o,
const std::map<std::string, UniValue::VType>& typesExpected, bool fAllowNull=false);
/**
* Run func nSeconds from now. Uses boost deadline timers.
@ -89,7 +90,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
//! Convert boost::asio address to CNetAddr
extern CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address);
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
typedef UniValue(*rpcfn_type)(const UniValue& params, bool fHelp);
class CRPCCommand
{
@ -115,11 +116,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;
@ -128,17 +129,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 std::string HelpRequiringPassphrase();
extern std::string HelpExampleCli(std::string methodname, std::string args);
@ -146,95 +147,95 @@ 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 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 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 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 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);
// in rest.cpp
extern bool HTTPReq_REST(AcceptedConnection *conn,

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 (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
if (test.size() < 2) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@ -50,13 +47,12 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
// Goal: test low-level base58 decoding functionality
BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
{
Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
std::vector<unsigned char> result;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
if (test.size() < 2) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@ -124,16 +120,15 @@ public:
// Goal: check that parsed keys match test payload
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
SelectParams(CBaseChainParams::MAIN);
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
if (test.size() < 3) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@ -141,7 +136,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
}
std::string exp_base58string = test[0].get_str();
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
const Object &metadata = test[2].get_obj();
const UniValue &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
if (isTestnet)
@ -183,12 +178,12 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
// Goal: check that generated keys match test vectors
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
std::vector<unsigned char> result;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
if (test.size() < 3) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
@ -196,7 +191,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
}
std::string exp_base58string = test[0].get_str();
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
const Object &metadata = test[2].get_obj();
const UniValue &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
if (isTestnet)
@ -251,15 +246,14 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
// Goal: check that base58 parsing code is robust against a variety of corrupted data
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
Array tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);

View file

@ -13,35 +13,36 @@
#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"));
string strMethod = vArgs[0];
vArgs.erase(vArgs.begin());
Array params = RPCConvertValues(strMethod, vArgs);
UniValue params = RPCConvertValues(strMethod, vArgs);
rpcfn_type method = tableRPC[strMethod]->actor;
try {
Value result = (*method)(params, false);
UniValue result = (*method)(params, false);
return result;
}
catch (const Object& objError) {
catch (const UniValue& objError) {
throw runtime_error(find_value(objError, "message").get_str());
}
}
@ -52,7 +53,7 @@ BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup)
BOOST_AUTO_TEST_CASE(rpc_rawparams)
{
// Test raw transaction API argument handling
Value r;
UniValue r;
BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error);
BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error);
@ -92,7 +93,7 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_AUTO_TEST_CASE(rpc_rawsign)
{
Value r;
UniValue r;
// input is a 1-of-2 multisig (so is output):
string prevout =
"[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
@ -111,20 +112,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;
}
@ -142,20 +143,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

@ -14,11 +14,12 @@
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.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;
@ -35,7 +36,7 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig)
// new, compressed:
const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
Value v;
UniValue v;
CBitcoinAddress address;
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
address.SetString(v.get_str());
@ -66,13 +67,13 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig)
BOOST_AUTO_TEST_CASE(rpc_wallet)
{
// Test RPC calls for various wallet statistics
Value r;
UniValue r;
LOCK2(cs_main, pwalletMain->cs_wallet);
CPubKey demoPubkey = pwalletMain->GenerateNewKey();
CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
Value retValue;
UniValue retValue;
string strAccount = "walletDemoAccount";
string strPurpose = "receive";
BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
@ -213,7 +214,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
*********************************/
BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error);
BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
Array arr = retValue.get_array();
UniValue arr = retValue.get_array();
BOOST_CHECK(arr.size() > 0);
BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get());
}

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 (unsigned int idx = 0; idx < json_good.size(); idx++) {
const UniValue& tv = json_good[idx];
tests_good.insert(tv.get_array().write());
}
BOOST_FOREACH(Value& tv, json_bad) {
tests_bad.insert(write_string(Value(tv.get_array()), true));
for (unsigned int idx = 0; idx < json_bad.size(); idx++) {
const UniValue& tv = json_bad[idx];
tests_bad.insert(tv.get_array().write());
}
}
@ -598,7 +598,7 @@ BOOST_AUTO_TEST_CASE(script_build)
BOOST_FOREACH(TestBuilder& test, good) {
test.Test(true);
std::string str = write_string(Value(test.GetJSON()), true);
std::string str = test.GetJSON().write();
#ifndef UPDATE_JSON_TESTS
if (tests_good.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment());
@ -608,7 +608,7 @@ BOOST_AUTO_TEST_CASE(script_build)
}
BOOST_FOREACH(TestBuilder& test, bad) {
test.Test(false);
std::string str = write_string(Value(test.GetJSON()), true);
std::string str = test.GetJSON().write();
#ifndef UPDATE_JSON_TESTS
if (tests_bad.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment());
@ -634,12 +634,11 @@ BOOST_AUTO_TEST_CASE(script_valid)
// Inner arrays are [ "scriptSig", "scriptPubKey", "flags" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
Array tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
UniValue tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
string strTest = write_string(tv, false);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments)
{
if (test.size() != 1) {
@ -660,13 +659,12 @@ BOOST_AUTO_TEST_CASE(script_valid)
BOOST_AUTO_TEST_CASE(script_invalid)
{
// Scripts that should evaluate as invalid
Array tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
UniValue tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
string strTest = write_string(tv, false);
if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments)
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
if (test.size() < 3) // Allow size > 2; extra stuff ignored (useful for comments)
{
if (test.size() != 1) {
BOOST_ERROR("Bad test: " << strTest);

View file

@ -16,12 +16,10 @@
#include <iostream>
#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
using namespace json_spirit;
extern Array read_json(const std::string& jsondata);
#include "univalue/univalue.h"
extern UniValue read_json(const std::string& jsondata);
// Old script.cpp SignatureHash function
uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
@ -168,12 +166,11 @@ BOOST_AUTO_TEST_CASE(sighash_test)
// Goal: check that SignatureHash generates correct hash
BOOST_AUTO_TEST_CASE(sighash_from_data)
{
Array tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
UniValue tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
std::string strTest = write_string(tv, false);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);

View file

@ -20,15 +20,16 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_writer_template.h"
#include "univalue/univalue.h"
using namespace std;
using namespace json_spirit;
// In script_tests.cpp
extern Array read_json(const std::string& jsondata);
extern UniValue read_json(const std::string& jsondata);
static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
(string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE)
@ -88,32 +89,31 @@ BOOST_AUTO_TEST_CASE(tx_valid)
// ... where all scripts are stringified scripts.
//
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
Array tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
ScriptError err;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
string strTest = write_string(tv, false);
if (test[0].type() == array_type)
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
if (test[0].isArray())
{
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type)
if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
Array inputs = test[0].get_array();
UniValue inputs = test[0].get_array();
bool fValid = true;
BOOST_FOREACH(Value& input, inputs)
{
if (input.type() != array_type)
for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
const UniValue& input = inputs[inpIdx];
if (!input.isArray())
{
fValid = false;
break;
}
Array vinput = input.get_array();
UniValue vinput = input.get_array();
if (vinput.size() != 3)
{
fValid = false;
@ -164,32 +164,31 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
// ... where all scripts are stringified scripts.
//
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
Array tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
ScriptError err;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
string strTest = write_string(tv, false);
if (test[0].type() == array_type)
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
if (test[0].isArray())
{
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type)
if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
Array inputs = test[0].get_array();
UniValue inputs = test[0].get_array();
bool fValid = true;
BOOST_FOREACH(Value& input, inputs)
{
if (input.type() != array_type)
for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
const UniValue& input = inputs[inpIdx];
if (!input.isArray())
{
fValid = false;
break;
}
Array vinput = input.get_array();
UniValue vinput = input.get_array();
if (vinput.size() != 3)
{
fValid = false;

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 == 9223372036854775807LL);
BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == 9223372036854775808LL);
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

@ -416,12 +416,25 @@ string DecodeBase32(const string& str)
return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size());
}
static bool ParsePrechecks(const std::string& str)
{
if (str.empty()) // No empty string allowed
return false;
if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
return false;
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
return false;
return true;
}
bool ParseInt32(const std::string& str, int32_t *out)
{
if (!ParsePrechecks(str))
return false;
char *endp = NULL;
errno = 0; // strtol will not set errno if valid
long int n = strtol(str.c_str(), &endp, 10);
if(out) *out = (int)n;
if(out) *out = (int32_t)n;
// Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
// platforms the size of these types may be different.
@ -430,6 +443,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

@ -49,6 +49,20 @@ int atoi(const std::string& str);
*/
bool ParseInt32(const std::string& str, int32_t *out);
/**
* Convert string to signed 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
bool ParseInt64(const std::string& str, int64_t *out);
/**
* Convert string to double with strict parse error feedback.
* @returns true if the entire string could be parsed as valid double,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
bool ParseDouble(const std::string& str, double *out);
template<typename T>
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
{

View file

@ -19,9 +19,8 @@
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "json/json_spirit_value.h"
#include "univalue/univalue.h"
using namespace json_spirit;
using namespace std;
void EnsureWalletIsUnlocked();
@ -70,10 +69,10 @@ std::string DecodeDumpString(const std::string &str) {
return ret.str();
}
Value importprivkey(const Array& params, bool fHelp)
UniValue importprivkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 3)
throw runtime_error(
@ -126,7 +125,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;
@ -141,13 +140,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(
@ -200,7 +199,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();
@ -214,13 +213,13 @@ Value importaddress(const Array& params, bool fHelp)
}
}
return Value::null;
return NullUniValue;
}
Value importwallet(const Array& params, bool fHelp)
UniValue importwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@ -318,13 +317,13 @@ Value importwallet(const Array& params, bool fHelp)
if (!fGood)
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
return Value::null;
return NullUniValue;
}
Value dumpprivkey(const Array& params, bool fHelp)
UniValue dumpprivkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@ -359,10 +358,10 @@ Value dumpprivkey(const Array& params, bool fHelp)
}
Value dumpwallet(const Array& params, bool fHelp)
UniValue dumpwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@ -421,5 +420,5 @@ Value dumpwallet(const Array& params, bool fHelp)
file << "\n";
file << "# End of dump\n";
file.close();
return Value::null;
return NullUniValue;
}

View file

@ -21,11 +21,9 @@
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include "univalue/univalue.h"
using namespace std;
using namespace json_spirit;
int64_t nWalletUnlockTime;
static CCriticalSection cs_nWalletUnlockTime;
@ -55,7 +53,7 @@ void EnsureWalletIsUnlocked()
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
}
void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
int confirms = wtx.GetDepthInMainChain();
entry.push_back(Pair("confirmations", confirms));
@ -69,7 +67,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
}
uint256 hash = wtx.GetHash();
entry.push_back(Pair("txid", hash.GetHex()));
Array conflicts;
UniValue conflicts(UniValue::VARR);
BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
conflicts.push_back(conflict.GetHex());
entry.push_back(Pair("walletconflicts", conflicts));
@ -79,7 +77,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair(item.first, item.second));
}
string AccountFromValue(const Value& value)
string AccountFromValue(const UniValue& value)
{
string strAccount = value.get_str();
if (strAccount == "*")
@ -87,10 +85,10 @@ string AccountFromValue(const Value& value)
return strAccount;
}
Value getnewaddress(const Array& params, bool fHelp)
UniValue getnewaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 1)
throw runtime_error(
@ -166,10 +164,10 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
return CBitcoinAddress(account.vchPubKey.GetID());
}
Value getaccountaddress(const Array& params, bool fHelp)
UniValue getaccountaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@ -191,17 +189,17 @@ Value getaccountaddress(const Array& params, bool fHelp)
// Parse the account first so we don't generate a key if there's an error
string strAccount = AccountFromValue(params[0]);
Value ret;
UniValue ret(UniValue::VSTR);
ret = GetAccountAddress(strAccount).ToString();
return ret;
}
Value getrawchangeaddress(const Array& params, bool fHelp)
UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 1)
throw runtime_error(
@ -233,10 +231,10 @@ Value getrawchangeaddress(const Array& params, bool fHelp)
}
Value setaccount(const Array& params, bool fHelp)
UniValue setaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -275,14 +273,14 @@ Value setaccount(const Array& params, bool fHelp)
else
throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
return Value::null;
return NullUniValue;
}
Value getaccount(const Array& params, bool fHelp)
UniValue getaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@ -311,10 +309,10 @@ Value getaccount(const Array& params, bool fHelp)
}
Value getaddressesbyaccount(const Array& params, bool fHelp)
UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@ -337,7 +335,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
string strAccount = AccountFromValue(params[0]);
// Find all addresses that have the given account
Array ret;
UniValue ret(UniValue::VARR);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
@ -379,10 +377,10 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
}
Value sendtoaddress(const Array& params, bool fHelp)
UniValue sendtoaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
@ -419,9 +417,9 @@ Value sendtoaddress(const Array& params, bool fHelp)
// Wallet comments
CWalletTx wtx;
if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
wtx.mapValue["comment"] = params[2].get_str();
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
wtx.mapValue["to"] = params[3].get_str();
bool fSubtractFeeFromAmount = false;
@ -435,10 +433,10 @@ Value sendtoaddress(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
Value listaddressgroupings(const Array& params, bool fHelp)
UniValue listaddressgroupings(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp)
throw runtime_error(
@ -465,14 +463,14 @@ Value listaddressgroupings(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
Array jsonGroupings;
UniValue jsonGroupings(UniValue::VARR);
map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
{
Array jsonGrouping;
UniValue jsonGrouping(UniValue::VARR);
BOOST_FOREACH(CTxDestination address, grouping)
{
Array addressInfo;
UniValue addressInfo(UniValue::VARR);
addressInfo.push_back(CBitcoinAddress(address).ToString());
addressInfo.push_back(ValueFromAmount(balances[address]));
{
@ -487,10 +485,10 @@ Value listaddressgroupings(const Array& params, bool fHelp)
return jsonGroupings;
}
Value signmessage(const Array& params, bool fHelp)
UniValue signmessage(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 2)
throw runtime_error(
@ -543,10 +541,10 @@ Value signmessage(const Array& params, bool fHelp)
return EncodeBase64(&vchSig[0], vchSig.size());
}
Value getreceivedbyaddress(const Array& params, bool fHelp)
UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -601,10 +599,10 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
}
Value getreceivedbyaccount(const Array& params, bool fHelp)
UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -690,10 +688,10 @@ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminef
}
Value getbalance(const Array& params, bool fHelp)
UniValue getbalance(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@ -765,10 +763,10 @@ Value getbalance(const Array& params, bool fHelp)
return ValueFromAmount(nBalance);
}
Value getunconfirmedbalance(const Array &params, bool fHelp)
UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 0)
throw runtime_error(
@ -781,10 +779,10 @@ Value getunconfirmedbalance(const Array &params, bool fHelp)
}
Value movecmd(const Array& params, bool fHelp)
UniValue movecmd(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 3 || params.size() > 5)
throw runtime_error(
@ -851,10 +849,10 @@ Value movecmd(const Array& params, bool fHelp)
}
Value sendfrom(const Array& params, bool fHelp)
UniValue sendfrom(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 3 || params.size() > 6)
throw runtime_error(
@ -896,9 +894,9 @@ Value sendfrom(const Array& params, bool fHelp)
CWalletTx wtx;
wtx.strFromAccount = strAccount;
if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
wtx.mapValue["comment"] = params[4].get_str();
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
wtx.mapValue["to"] = params[5].get_str();
EnsureWalletIsUnlocked();
@ -914,10 +912,10 @@ Value sendfrom(const Array& params, bool fHelp)
}
Value sendmany(const Array& params, bool fHelp)
UniValue sendmany(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
@ -958,17 +956,17 @@ Value sendmany(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = AccountFromValue(params[0]);
Object sendTo = params[1].get_obj();
UniValue sendTo = params[1].get_obj();
int nMinDepth = 1;
if (params.size() > 2)
nMinDepth = params[2].get_int();
CWalletTx wtx;
wtx.strFromAccount = strAccount;
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
wtx.mapValue["comment"] = params[3].get_str();
Array subtractFeeFromAmount;
UniValue subtractFeeFromAmount(UniValue::VARR);
if (params.size() > 4)
subtractFeeFromAmount = params[4].get_array();
@ -976,24 +974,27 @@ Value sendmany(const Array& params, bool fHelp)
vector<CRecipient> vecSend;
CAmount totalAmount = 0;
BOOST_FOREACH(const Pair& s, sendTo)
vector<string> keys = sendTo.getKeys();
BOOST_FOREACH(const string& name_, keys)
{
CBitcoinAddress address(s.name_);
CBitcoinAddress address(name_);
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
if (setAddress.count(address))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
setAddress.insert(address);
CScript scriptPubKey = GetScriptForDestination(address.Get());
CAmount nAmount = AmountFromValue(s.value_);
CAmount nAmount = AmountFromValue(sendTo[name_]);
totalAmount += nAmount;
bool fSubtractFeeFromAmount = false;
BOOST_FOREACH(const Value& addr, subtractFeeFromAmount)
if (addr.get_str() == s.name_)
for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
const UniValue& addr = subtractFeeFromAmount[idx];
if (addr.get_str() == name_)
fSubtractFeeFromAmount = true;
}
CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
@ -1021,12 +1022,12 @@ Value sendmany(const Array& params, bool fHelp)
}
// Defined in rpcmisc.cpp
extern CScript _createmultisig_redeemScript(const Array& params);
extern CScript _createmultisig_redeemScript(const UniValue& params);
Value addmultisigaddress(const Array& params, bool fHelp)
UniValue addmultisigaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 2 || params.size() > 3)
{
@ -1086,7 +1087,7 @@ struct tallyitem
}
};
Value ListReceived(const Array& params, bool fByAccounts)
UniValue ListReceived(const UniValue& params, bool fByAccounts)
{
// Minimum confirmations
int nMinDepth = 1;
@ -1136,7 +1137,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
}
// Reply
Array ret;
UniValue ret(UniValue::VARR);
map<string, tallyitem> mapAccountTally;
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
{
@ -1165,14 +1166,14 @@ Value ListReceived(const Array& params, bool fByAccounts)
}
else
{
Object obj;
UniValue obj(UniValue::VOBJ);
if(fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
obj.push_back(Pair("address", address.ToString()));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
Array transactions;
UniValue transactions(UniValue::VARR);
if (it != mapTally.end())
{
BOOST_FOREACH(const uint256& item, (*it).second.txids)
@ -1191,7 +1192,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
CAmount nAmount = (*it).second.nAmount;
int nConf = (*it).second.nConf;
Object obj;
UniValue obj(UniValue::VOBJ);
if((*it).second.fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
obj.push_back(Pair("account", (*it).first));
@ -1204,10 +1205,10 @@ Value ListReceived(const Array& params, bool fByAccounts)
return ret;
}
Value listreceivedbyaddress(const Array& params, bool fHelp)
UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@ -1241,10 +1242,10 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
return ListReceived(params, false);
}
Value listreceivedbyaccount(const Array& params, bool fHelp)
UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@ -1277,14 +1278,14 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
return ListReceived(params, true);
}
static void MaybePushAddress(Object & entry, const CTxDestination &dest)
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
{
CBitcoinAddress addr;
if (addr.Set(dest))
entry.push_back(Pair("address", addr.ToString()));
}
void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
{
CAmount nFee;
string strSentAccount;
@ -1301,7 +1302,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
{
BOOST_FOREACH(const COutputEntry& s, listSent)
{
Object entry;
UniValue entry(UniValue::VOBJ);
if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", strSentAccount));
@ -1326,7 +1327,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
account = pwalletMain->mapAddressBook[r.destination].name;
if (fAllAccounts || (account == strAccount))
{
Object entry;
UniValue entry(UniValue::VOBJ);
if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", account));
@ -1354,13 +1355,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
}
}
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
{
bool fAllAccounts = (strAccount == string("*"));
if (fAllAccounts || acentry.strAccount == strAccount)
{
Object entry;
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("account", acentry.strAccount));
entry.push_back(Pair("category", "move"));
entry.push_back(Pair("time", acentry.nTime));
@ -1371,10 +1372,10 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar
}
}
Value listtransactions(const Array& params, bool fHelp)
UniValue listtransactions(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 4)
throw runtime_error(
@ -1449,7 +1450,7 @@ Value listtransactions(const Array& params, bool fHelp)
if (nFrom < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
Array ret;
UniValue ret(UniValue::VARR);
std::list<CAccountingEntry> acentries;
CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
@ -1472,23 +1473,30 @@ Value listtransactions(const Array& params, bool fHelp)
nFrom = ret.size();
if ((nFrom + nCount) > (int)ret.size())
nCount = ret.size() - nFrom;
Array::iterator first = ret.begin();
vector<UniValue> arrTmp = ret.getValues();
vector<UniValue>::iterator first = arrTmp.begin();
std::advance(first, nFrom);
Array::iterator last = ret.begin();
vector<UniValue>::iterator last = arrTmp.begin();
std::advance(last, nFrom+nCount);
if (last != ret.end()) ret.erase(last, ret.end());
if (first != ret.begin()) ret.erase(ret.begin(), first);
if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
std::reverse(ret.begin(), ret.end()); // Return oldest to newest
std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
ret.clear();
ret.setArray();
ret.push_backV(arrTmp);
return ret;
}
Value listaccounts(const Array& params, bool fHelp)
UniValue listaccounts(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 2)
throw runtime_error(
@ -1558,17 +1566,17 @@ Value listaccounts(const Array& params, bool fHelp)
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
Object ret;
UniValue ret(UniValue::VOBJ);
BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
}
return ret;
}
Value listsinceblock(const Array& params, bool fHelp)
UniValue listsinceblock(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp)
throw runtime_error(
@ -1636,7 +1644,7 @@ Value listsinceblock(const Array& params, bool fHelp)
int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
Array transactions;
UniValue transactions(UniValue::VARR);
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
{
@ -1649,17 +1657,17 @@ Value listsinceblock(const Array& params, bool fHelp)
CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
Object ret;
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("transactions", transactions));
ret.push_back(Pair("lastblock", lastblock.GetHex()));
return ret;
}
Value gettransaction(const Array& params, bool fHelp)
UniValue gettransaction(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -1707,7 +1715,7 @@ Value gettransaction(const Array& params, bool fHelp)
if(params[1].get_bool())
filter = filter | ISMINE_WATCH_ONLY;
Object entry;
UniValue entry(UniValue::VOBJ);
if (!pwalletMain->mapWallet.count(hash))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
@ -1723,7 +1731,7 @@ Value gettransaction(const Array& params, bool fHelp)
WalletTxToJSON(wtx, entry);
Array details;
UniValue details(UniValue::VARR);
ListTransactions(wtx, "*", 0, false, details, filter);
entry.push_back(Pair("details", details));
@ -1734,10 +1742,10 @@ Value gettransaction(const Array& params, bool fHelp)
}
Value backupwallet(const Array& params, bool fHelp)
UniValue backupwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
@ -1756,14 +1764,14 @@ Value backupwallet(const Array& params, bool fHelp)
if (!BackupWallet(*pwalletMain, strDest))
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
return Value::null;
return NullUniValue;
}
Value keypoolrefill(const Array& params, bool fHelp)
UniValue keypoolrefill(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 1)
throw runtime_error(
@ -1793,7 +1801,7 @@ Value keypoolrefill(const Array& params, bool fHelp)
if (pwalletMain->GetKeyPoolSize() < kpSize)
throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
return Value::null;
return NullUniValue;
}
@ -1804,10 +1812,10 @@ static void LockWallet(CWallet* pWallet)
pWallet->Lock();
}
Value walletpassphrase(const Array& params, bool fHelp)
UniValue walletpassphrase(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
throw runtime_error(
@ -1860,14 +1868,14 @@ Value walletpassphrase(const Array& params, bool fHelp)
nWalletUnlockTime = GetTime() + nSleepTime;
RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
return Value::null;
return NullUniValue;
}
Value walletpassphrasechange(const Array& params, bool fHelp)
UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
throw runtime_error(
@ -1906,14 +1914,14 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
return Value::null;
return NullUniValue;
}
Value walletlock(const Array& params, bool fHelp)
UniValue walletlock(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
throw runtime_error(
@ -1945,14 +1953,14 @@ Value walletlock(const Array& params, bool fHelp)
nWalletUnlockTime = 0;
}
return Value::null;
return NullUniValue;
}
Value encryptwallet(const Array& params, bool fHelp)
UniValue encryptwallet(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
throw runtime_error(
@ -2006,10 +2014,10 @@ Value encryptwallet(const Array& params, bool fHelp)
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
}
Value lockunspent(const Array& params, bool fHelp)
UniValue lockunspent(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@ -2050,9 +2058,9 @@ Value lockunspent(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
if (params.size() == 1)
RPCTypeCheck(params, boost::assign::list_of(bool_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
else
RPCTypeCheck(params, boost::assign::list_of(bool_type)(array_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
bool fUnlock = params[0].get_bool();
@ -2062,14 +2070,14 @@ Value lockunspent(const Array& params, bool fHelp)
return true;
}
Array outputs = params[1].get_array();
BOOST_FOREACH(Value& output, outputs)
{
if (output.type() != obj_type)
UniValue outputs = params[1].get_array();
for (unsigned int idx = 0; idx < outputs.size(); idx++) {
const UniValue& output = outputs[idx];
if (!output.isObject())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
const Object& o = output.get_obj();
const UniValue& o = output.get_obj();
RPCTypeCheck(o, boost::assign::map_list_of("txid", str_type)("vout", int_type));
RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
string txid = find_value(o, "txid").get_str();
if (!IsHex(txid))
@ -2090,10 +2098,10 @@ Value lockunspent(const Array& params, bool fHelp)
return true;
}
Value listlockunspent(const Array& params, bool fHelp)
UniValue listlockunspent(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 0)
throw runtime_error(
@ -2126,10 +2134,10 @@ Value listlockunspent(const Array& params, bool fHelp)
vector<COutPoint> vOutpts;
pwalletMain->ListLockedCoins(vOutpts);
Array ret;
UniValue ret(UniValue::VARR);
BOOST_FOREACH(COutPoint &outpt, vOutpts) {
Object o;
UniValue o(UniValue::VOBJ);
o.push_back(Pair("txid", outpt.hash.GetHex()));
o.push_back(Pair("vout", (int)outpt.n));
@ -2139,10 +2147,10 @@ Value listlockunspent(const Array& params, bool fHelp)
return ret;
}
Value settxfee(const Array& params, bool fHelp)
UniValue settxfee(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 1)
throw runtime_error(
@ -2168,10 +2176,10 @@ Value settxfee(const Array& params, bool fHelp)
return true;
}
Value getwalletinfo(const Array& params, bool fHelp)
UniValue getwalletinfo(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 0)
throw runtime_error(
@ -2195,7 +2203,7 @@ Value getwalletinfo(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
Object obj;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
@ -2208,10 +2216,10 @@ Value getwalletinfo(const Array& params, bool fHelp)
return obj;
}
Value resendwallettransactions(const Array& params, bool fHelp)
UniValue resendwallettransactions(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() != 0)
throw runtime_error(
@ -2225,7 +2233,7 @@ Value resendwallettransactions(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
Array result;
UniValue result(UniValue::VARR);
BOOST_FOREACH(const uint256& txid, txids)
{
result.push_back(txid.ToString());
@ -2233,10 +2241,10 @@ Value resendwallettransactions(const Array& params, bool fHelp)
return result;
}
Value listunspent(const Array& params, bool fHelp)
UniValue listunspent(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
return NullUniValue;
if (fHelp || params.size() > 3)
throw runtime_error(
@ -2274,7 +2282,7 @@ Value listunspent(const Array& params, bool fHelp)
+ HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
);
RPCTypeCheck(params, boost::assign::list_of(int_type)(int_type)(array_type));
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
int nMinDepth = 1;
if (params.size() > 0)
@ -2286,8 +2294,9 @@ Value listunspent(const Array& params, bool fHelp)
set<CBitcoinAddress> setAddress;
if (params.size() > 2) {
Array inputs = params[2].get_array();
BOOST_FOREACH(Value& input, inputs) {
UniValue inputs = params[2].get_array();
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
CBitcoinAddress address(input.get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
@ -2297,7 +2306,7 @@ Value listunspent(const Array& params, bool fHelp)
}
}
Array results;
UniValue results(UniValue::VARR);
vector<COutput> vecOutputs;
assert(pwalletMain != NULL);
LOCK2(cs_main, pwalletMain->cs_wallet);
@ -2317,7 +2326,7 @@ Value listunspent(const Array& params, bool fHelp)
CAmount nValue = out.tx->vout[out.i].nValue;
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
Object entry;
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
entry.push_back(Pair("vout", out.i));
CTxDestination address;