Skip to content

Commit b5befa4

Browse files
committed
Add bitcoind_rest interface methods, dispatch, a stub hander.
1 parent e728915 commit b5befa4

File tree

4 files changed

+151
-7
lines changed

4 files changed

+151
-7
lines changed

include/bitcoin/node/interfaces/bitcoind_rest.hpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,32 @@ namespace interface {
2828

2929
struct bitcoind_rest_methods
3030
{
31+
// github.com/bitcoin/bitcoin/blob/master/doc/REST-interface.md
3132
static constexpr std::tuple methods
3233
{
33-
method<"rest1">{},
34+
// blocks (block_part is bin|hex only)
35+
method<"block", uint8_t, system::hash_cptr>{ "media", "hash" },
36+
method<"block_hash", uint8_t, uint32_t>{ "media", "height" },
37+
method<"block_txs", uint8_t, system::hash_cptr>{ "media", "hash" },
38+
method<"block_headers", uint8_t, system::hash_cptr, uint32_t>{ "media", "hash", "count" },
39+
method<"block_part", uint8_t, system::hash_cptr, uint32_t, uint32_t>{ "media", "hash", "offset", "size" },
40+
method<"block_spent_tx_outputs", uint8_t, system::hash_cptr>{ "media", "hash" },
41+
42+
// client filters
43+
method<"block_filter", uint8_t, system::hash_cptr, uint8_t>{ "media", "hash", "type" },
44+
method<"block_filter_headers", uint8_t, system::hash_cptr, uint8_t>{ "media", "hash", "type" },
45+
46+
// unspent outputs
47+
method<"get_utxos", uint8_t, system::hash_cptr, uint8_t>{ "media", "hash", "type" },
48+
method<"get_utxos_confirmed", uint8_t, system::hash_cptr, uint8_t>{ "media", "hash", "type" },
49+
50+
// mempool (json only)
51+
method<"mempool", optional<true>, optional<false>>{ "verbose", "sequence" },
52+
53+
// info (json only)
54+
method<"chain_information">{},
55+
method<"mempool_information">{},
56+
method<"fork_information", nullable<system::hash_cptr>>{ "hash" }
3457
};
3558

3659
template <typename... Args>
@@ -40,7 +63,20 @@ struct bitcoind_rest_methods
4063
using at = method_at<methods, Index>;
4164

4265
// Derive this from above in c++26 using reflection.
43-
using rest1 = at<0>;
66+
using block = at<0>;
67+
using block_hash = at<1>;
68+
using block_txs = at<2>;
69+
using block_headers = at<3>;
70+
using block_part = at<4>;
71+
using block_spent_tx_outputs = at<5>;
72+
using block_filter = at<6>;
73+
using block_filter_headers = at<7>;
74+
using get_utxos = at<8>;
75+
using get_utxos_confirmed = at<9>;
76+
using mempool = at<10>;
77+
using chain_information = at<11>;
78+
using mempool_information = at<12>;
79+
using fork_information = at<13>;
4480
};
4581

4682
} // namespace interface

include/bitcoin/node/protocols/protocol_bitcoind_rest.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,18 @@ class BCN_API protocol_bitcoind_rest
4747

4848
/// Public start is required.
4949
void start() NOEXCEPT override;
50+
void stopping(const code& ec) NOEXCEPT override;
5051

5152
protected:
52-
/// TODO: Dispatch.
53-
/// TODO: Handlers.
53+
using get = network::http::method::get;
54+
55+
/// Dispatch.
56+
void handle_receive_get(const code& ec,
57+
const get::cptr& get) NOEXCEPT override;
58+
59+
/// REST interface handlers.
60+
bool handle_get_block(const code& ec, rest_interface::block,
61+
uint8_t media, system::hash_cptr hash) NOEXCEPT;
5462

5563
private:
5664
template <class Derived, typename Method, typename... Args>

src/protocols/protocol_bitcoind_rest.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@
2424
namespace libbitcoin {
2525
namespace node {
2626

27+
#define CLASS protocol_bitcoind_rest
28+
#define SUBSCRIBE_BITCOIND(method, ...) \
29+
subscribe<CLASS>(&CLASS::method, __VA_ARGS__)
30+
31+
using namespace system;
32+
using namespace network::rpc;
33+
using namespace network::http;
34+
using namespace std::placeholders;
35+
using namespace boost::json;
36+
37+
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
38+
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
39+
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
40+
2741
// Start.
2842
// ----------------------------------------------------------------------------
2943

@@ -36,8 +50,93 @@ void protocol_bitcoind_rest::start() NOEXCEPT
3650
if (started())
3751
return;
3852

53+
SUBSCRIBE_BITCOIND(handle_get_block, _1, _2, _3, _4);
3954
protocol_bitcoind_rpc::start();
4055
}
4156

57+
void protocol_bitcoind_rest::stopping(const code& ec) NOEXCEPT
58+
{
59+
BC_ASSERT(stranded());
60+
rest_dispatcher_.stop(ec);
61+
protocol_bitcoind_rpc::stopping(ec);
62+
}
63+
64+
// Dispatch.
65+
// ----------------------------------------------------------------------------
66+
67+
// Base rpc protocol handles options and post, this derived handles get.
68+
void protocol_bitcoind_rest::handle_receive_get(const code& ec,
69+
const get::cptr& get) NOEXCEPT
70+
{
71+
BC_ASSERT(stranded());
72+
73+
if (stopped(ec))
74+
return;
75+
76+
// Enforce http host header (if any hosts are configured).
77+
if (!is_allowed_host(*get, get->version()))
78+
{
79+
send_bad_host(*get);
80+
return;
81+
}
82+
83+
// Enforce http origin policy (if any origins are configured).
84+
if (!is_allowed_origin(*get, get->version()))
85+
{
86+
send_forbidden(*get);
87+
return;
88+
}
89+
90+
// The post is saved off during asynchonous handling and used in send_json
91+
// to formulate response headers, isolating handlers from http semantics.
92+
set_request(get);
93+
94+
////if (const auto code = rest_dispatcher_.notify({}))
95+
//// stop(code);
96+
protocol_bitcoind_rpc::handle_receive_get(ec, get);
97+
}
98+
99+
// Handlers.
100+
// ----------------------------------------------------------------------------
101+
102+
constexpr auto data = to_value(media_type::application_octet_stream);
103+
constexpr auto json = to_value(media_type::application_json);
104+
constexpr auto text = to_value(media_type::text_plain);
105+
106+
bool protocol_bitcoind_rest::handle_get_block(const code& ec,
107+
rest_interface::block, uint8_t , system::hash_cptr ) NOEXCEPT
108+
{
109+
if (stopped(ec))
110+
return false;
111+
112+
////const auto& query = archive();
113+
////if (const auto block = query.get_block(query.to_header(*hash), true))
114+
////{
115+
//// const auto size = block->serialized_size(true);
116+
//// switch (media)
117+
//// {
118+
//// case data:
119+
//// send_chunk(to_bin(*block, size, true));
120+
//// return true;
121+
//// case text:
122+
//// send_text(to_hex(*block, size, true));
123+
//// return true;
124+
//// case json:
125+
//// send_json(value_from(block), two * size);
126+
//// return true;
127+
//// }
128+
////}
129+
130+
send_not_found();
131+
return true;
132+
}
133+
134+
// private
135+
// ----------------------------------------------------------------------------
136+
137+
BC_POP_WARNING()
138+
BC_POP_WARNING()
139+
BC_POP_WARNING()
140+
42141
} // namespace node
43142
} // namespace libbitcoin

src/protocols/protocol_bitcoind_rpc.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ void protocol_bitcoind_rpc::handle_receive_post(const code& ec,
154154

155155
// The post is saved off during asynchonous handling and used in send_json
156156
// to formulate response headers, isolating handlers from http semantics.
157-
set_post(post);
157+
set_request(post);
158158

159159
if (const auto code = rpc_dispatcher_.notify(request))
160160
stop(code);
@@ -310,13 +310,14 @@ void protocol_bitcoind_rpc::send_json(boost::json::value&& model,
310310
SEND(std::move(response), handle_complete, _1, error::success);
311311
}
312312

313-
void protocol_bitcoind_rpc::set_post(const post::cptr& post) NOEXCEPT
313+
void protocol_bitcoind_rpc::set_request(const post::cptr& post) NOEXCEPT
314314
{
315315
BC_ASSERT(post);
316316
post_ = post;
317317
}
318318

319-
const protocol_bitcoind_rpc::post& protocol_bitcoind_rpc::get_post() const NOEXCEPT
319+
const protocol_bitcoind_rpc::post& protocol_bitcoind_rpc::
320+
set_request() const NOEXCEPT
320321
{
321322
BC_ASSERT(post_);
322323
return *post_;

0 commit comments

Comments
 (0)