Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/bitcoin/server/interfaces/bitcoind_rpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct bitcoind_rpc_methods
{
/// Blockchain methods.
method<"getbestblockhash">{},
method<"getblock", string_t, optional<1.0>>{ "blockhash", "verbosity" },
method<"getblock", string_t, optional<empty::value>>{ "blockhash", "verbosity" },
method<"getblockchaininfo">{},
method<"getblockcount">{},
method<"getblockfilter", string_t, optional<"basic"_t>>{ "blockhash", "filtertype" },
Expand Down Expand Up @@ -73,7 +73,7 @@ struct bitcoind_rpc_methods
method<"getnetworkinfo">{},

/// Rawtransactions methods (implemented).
method<"getrawtransaction", string_t, optional<0.0>, optional<""_t>>{ "txid", "verbosity", "blockhash" },
method<"getrawtransaction", string_t, optional<empty::value>, optional<""_t>>{ "txid", "verbosity", "blockhash" },
method<"sendrawtransaction", string_t, optional<0.0>>{ "hexstring", "maxfeerate" }
////method<"getpeerinfo">{},
////method<"listbanned">{},
Expand Down
7 changes: 5 additions & 2 deletions include/bitcoin/server/protocols/protocol_bitcoind_rpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class BCS_API protocol_bitcoind_rpc
rpc_interface::get_best_block_hash) NOEXCEPT;
bool handle_get_block(const code& ec,
rpc_interface::get_block, const std::string&,
double verbosity) NOEXCEPT;
const network::rpc::value_t& verbosity) NOEXCEPT;
bool handle_get_block_chain_info(const code& ec,
rpc_interface::get_block_chain_info) NOEXCEPT;
bool handle_get_block_count(const code& ec,
Expand Down Expand Up @@ -105,14 +105,17 @@ class BCS_API protocol_bitcoind_rpc
rpc_interface::get_network_info) NOEXCEPT;
bool handle_get_raw_transaction(const code& ec,
rpc_interface::get_raw_transaction, const std::string& txid,
double verbose, const std::string& blockhash) NOEXCEPT;
const network::rpc::value_t& verbosity,
const std::string& blockhash) NOEXCEPT;
bool handle_send_raw_transaction(const code& ec,
rpc_interface::send_raw_transaction, const std::string& hexstring,
double maxfeerate) NOEXCEPT;

/// Json context helpers (shared with rest, defined in *_json.cpp).
static uint32_t median_time_past(const node::query& query,
const database::header_link& link) NOEXCEPT;
static bool parse_verbosity(double& verbosity,
const network::rpc::value_t& value, double missing) NOEXCEPT;
static void inject_block_context(boost::json::object& out,
const node::query& query, const database::header_link& link,
const system::chain::header& header) NOEXCEPT;
Expand Down
18 changes: 16 additions & 2 deletions src/protocols/bitcoind/protocol_bitcoind_rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,18 @@ bool protocol_bitcoind_rpc::handle_get_best_block_hash(const code& ec,

bool protocol_bitcoind_rpc::handle_get_block(const code& ec,
rpc_interface::get_block, const std::string& blockhash,
double verbosity) NOEXCEPT
const network::rpc::value_t& verbosity_value) NOEXCEPT
{
if (stopped(ec))
return false;

double verbosity{};
if (!parse_verbosity(verbosity, verbosity_value, 1.0))
{
send_error(error::invalid_argument);
return true;
}

hash_digest hash{};
if (!decode_hash(hash, blockhash))
{
Expand Down Expand Up @@ -568,11 +575,18 @@ bool protocol_bitcoind_rpc::handle_get_network_info(const code& ec,

bool protocol_bitcoind_rpc::handle_get_raw_transaction(const code& ec,
rpc_interface::get_raw_transaction, const std::string& txid,
double verbose, const std::string&) NOEXCEPT
const network::rpc::value_t& verbosity_value, const std::string&) NOEXCEPT
{
if (stopped(ec))
return false;

double verbose{};
if (!parse_verbosity(verbose, verbosity_value, 0.0))
{
send_error(error::invalid_argument);
return true;
}

// The blockhash hint is unused: libbitcoin archives all tx (global index).
hash_digest hash{};
if (!decode_hash(hash, txid))
Expand Down
23 changes: 23 additions & 0 deletions src/protocols/bitcoind/protocol_bitcoind_rpc_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
#include <bitcoin/server/protocols/protocol_bitcoind_rpc.hpp>

#include <variant>
#include <vector>
#include <bitcoin/server/define.hpp>

namespace libbitcoin {
Expand All @@ -32,6 +34,27 @@ uint32_t protocol_bitcoind_rpc::median_time_past(const node::query& query,
return query.get_context(ctx, link) ? ctx.median_time_past : 0_u32;
}

// bitcoind accepts boolean or number for the getblock/getrawtransaction
// verbosity parameters (both were originally boolean and remain so in
// common clients), so a typed number subscription cannot match them.
bool protocol_bitcoind_rpc::parse_verbosity(double& verbosity,
const network::rpc::value_t& value, double missing) NOEXCEPT
{
using namespace network::rpc;
const auto& inner = value.value();

if (std::holds_alternative<null_t>(inner))
verbosity = missing;
else if (std::holds_alternative<boolean_t>(inner))
verbosity = std::get<boolean_t>(inner) ? 1.0 : 0.0;
else if (std::holds_alternative<number_t>(inner))
verbosity = std::get<number_t>(inner);
else
return false;

return true;
}

void protocol_bitcoind_rpc::inject_block_context(boost::json::object& out,
const node::query& query, const database::header_link& link,
const chain::header& header) NOEXCEPT
Expand Down
45 changes: 45 additions & 0 deletions test/protocols/bitcoind/bitcoind_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct json
: server::protocol_bitcoind_rpc
{
using protocol_bitcoind_rpc::median_time_past;
using protocol_bitcoind_rpc::parse_verbosity;
using protocol_bitcoind_rpc::inject_block_context;
using protocol_bitcoind_rpc::inject_tx_context;
using protocol_bitcoind_rpc::header_to_bitcoind;
Expand Down Expand Up @@ -62,6 +63,50 @@ BOOST_AUTO_TEST_CASE(bitcoind_json__header_to_bitcoind__block1_header__maps_fiel

BOOST_AUTO_TEST_SUITE_END()

// parse_verbosity
// ----------------------------------------------------------------------------

BOOST_AUTO_TEST_SUITE(bitcoind_parse_verbosity_tests)

using rpc_value_t = network::rpc::value_t;

BOOST_AUTO_TEST_CASE(bitcoind_json__parse_verbosity__missing__defaulted)
{
double verbosity{};
BOOST_REQUIRE(json::parse_verbosity(verbosity, rpc_value_t{}, 42.0));
BOOST_REQUIRE_EQUAL(verbosity, 42.0);
}

BOOST_AUTO_TEST_CASE(bitcoind_json__parse_verbosity__boolean_true__one)
{
double verbosity{};
BOOST_REQUIRE(json::parse_verbosity(verbosity, rpc_value_t{ true }, 0.0));
BOOST_REQUIRE_EQUAL(verbosity, 1.0);
}

BOOST_AUTO_TEST_CASE(bitcoind_json__parse_verbosity__boolean_false__zero)
{
double verbosity{};
BOOST_REQUIRE(json::parse_verbosity(verbosity, rpc_value_t{ false }, 1.0));
BOOST_REQUIRE_EQUAL(verbosity, 0.0);
}

BOOST_AUTO_TEST_CASE(bitcoind_json__parse_verbosity__number__passed_through)
{
double verbosity{};
BOOST_REQUIRE(json::parse_verbosity(verbosity, rpc_value_t{ 2.0 }, 0.0));
BOOST_REQUIRE_EQUAL(verbosity, 2.0);
}

BOOST_AUTO_TEST_CASE(bitcoind_json__parse_verbosity__string__false)
{
double verbosity{};
const network::rpc::string_t value{ "1" };
BOOST_REQUIRE(!json::parse_verbosity(verbosity, rpc_value_t{ value }, 0.0));
}

BOOST_AUTO_TEST_SUITE_END()

// ----------------------------------------------------------------------------

struct bitcoind_json_setup_fixture
Expand Down
Loading