Skip to content

Commit 7032ffb

Browse files
committed
Implement handle_blockchain_number_of_blocks_subscribe.
1 parent d80726a commit 7032ffb

4 files changed

Lines changed: 82 additions & 31 deletions

File tree

include/bitcoin/server/protocols/protocol_electrum.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ class BCS_API protocol_electrum
168168
void blockchain_block_headers(size_t starting, size_t quantity,
169169
size_t waypoint, bool multiplicity) NOEXCEPT;
170170

171-
/// Notify client of new header.
171+
/// Notify client of newly organized block.
172+
void do_height(node::header_t link) NOEXCEPT;
172173
void do_header(node::header_t link) NOEXCEPT;
173174

174175
inline bool at_least(server::electrum::version version) const NOEXCEPT
@@ -196,7 +197,8 @@ class BCS_API protocol_electrum
196197

197198
// These are thread safe.
198199
const options_t& options_;
199-
std::atomic_bool subscribed_{};
200+
std::atomic_bool subscribed_height_{};
201+
std::atomic_bool subscribed_header_{};
200202

201203
// This is mostly thread safe, and used in a thread safe manner.
202204
const channel_t::ptr channel_;

src/protocols/electrum/protocol_electrum.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ namespace server {
2929

3030
#define CLASS protocol_electrum
3131

32+
using namespace system;
33+
using namespace network::rpc;
3234
using namespace std::placeholders;
3335

3436
// Start.
@@ -118,7 +120,13 @@ bool protocol_electrum::handle_event(const code&, node::chase event_,
118120
{
119121
case node::chase::organized:
120122
{
121-
if (subscribed_.load(std::memory_order_relaxed))
123+
if (subscribed_height_.load(std::memory_order_relaxed))
124+
{
125+
BC_ASSERT(std::holds_alternative<node::header_t>(value));
126+
POST(do_height, std::get<node::header_t>(value));
127+
}
128+
129+
if (subscribed_header_.load(std::memory_order_relaxed))
122130
{
123131
BC_ASSERT(std::holds_alternative<node::header_t>(value));
124132
POST(do_header, std::get<node::header_t>(value));
@@ -135,5 +143,50 @@ bool protocol_electrum::handle_event(const code&, node::chase event_,
135143
return true;
136144
}
137145

146+
// Notifier for handle_blockchain_number_of_blocks_subscribe events.
147+
void protocol_electrum::do_height(node::header_t link) NOEXCEPT
148+
{
149+
BC_ASSERT(stranded());
150+
151+
const auto& query = archive();
152+
const auto height = query.get_height(link);
153+
154+
if (height.is_terminal())
155+
{
156+
LOGF("Electrum::do_height, object not found (" << link << ").");
157+
return;
158+
}
159+
160+
send_notification("blockchain.numblocks.subscribe",
161+
{
162+
array_t{ height.value }
163+
}, 48, BIND(complete, _1));
164+
}
165+
166+
// Notifier for blockchain_headers_subscribe events.
167+
void protocol_electrum::do_header(node::header_t link) NOEXCEPT
168+
{
169+
BC_ASSERT(stranded());
170+
171+
const auto& query = archive();
172+
const auto height = query.get_height(link);
173+
const auto header = query.get_wire_header(link);
174+
175+
if (height.is_terminal())
176+
{
177+
LOGF("Electrum::do_header, object not found (" << link << ").");
178+
return;
179+
}
180+
181+
send_notification("blockchain.headers.subscribe",
182+
{
183+
object_t
184+
{
185+
{ "height", height.value },
186+
{ "hex", encode_base16(header) }
187+
}
188+
}, 64, BIND(complete, _1));
189+
}
190+
138191
} // namespace server
139192
} // namespace libbitcoin

src/protocols/electrum/protocol_electrum_headers.cpp

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ void protocol_electrum::handle_blockchain_number_of_blocks_subscribe(
4646
return;
4747
}
4848

49-
// TODO: implement.
50-
send_code(error::not_implemented);
49+
subscribed_height_.store(true, std::memory_order_relaxed);
50+
const auto top_height = archive().get_top_confirmed();
51+
send_result(top_height, 42, BIND(complete, _1));
5152
}
5253

5354
void protocol_electrum::handle_blockchain_block_get_chunk(const code& ec,
@@ -292,7 +293,7 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec,
292293
return;
293294
}
294295

295-
subscribed_.store(true, std::memory_order_relaxed);
296+
subscribed_header_.store(true, std::memory_order_relaxed);
296297
send_result(
297298
{
298299
object_t
@@ -303,31 +304,6 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec,
303304
}, 256, BIND(complete, _1));
304305
}
305306

306-
// Notifier for blockchain_headers_subscribe events.
307-
void protocol_electrum::do_header(node::header_t link) NOEXCEPT
308-
{
309-
BC_ASSERT(stranded());
310-
311-
const auto& query = archive();
312-
const auto height = query.get_height(link);
313-
const auto header = query.get_wire_header(link);
314-
315-
if (height.is_terminal())
316-
{
317-
LOGF("Electrum::do_header, object not found (" << link << ").");
318-
return;
319-
}
320-
321-
send_notification("blockchain.headers.subscribe",
322-
{
323-
object_t
324-
{
325-
{ "height", height.value },
326-
{ "hex", encode_base16(header) }
327-
}
328-
}, 100, BIND(complete, _1));
329-
}
330-
331307
BC_POP_WARNING()
332308

333309
} // namespace server

test/protocols/electrum/electrum_headers.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ static const code wrong_version{ server::error::wrong_version };
2727
static const code target_overflow{ server::error::target_overflow };
2828
static const code invalid_argument{ server::error::invalid_argument };
2929

30+
// blockchain.numblocks.subscribe
31+
32+
BOOST_AUTO_TEST_CASE(electrum__blockchain_number_of_blocks_subscribe__obsoleted_version__wrong_version)
33+
{
34+
BOOST_REQUIRE(handshake(electrum::version::v1_1));
35+
36+
const auto response = get(R"({"id":1001,"method":"blockchain.numblocks.subscribe","params":[]})" "\n");
37+
REQUIRE_NO_THROW_TRUE(response.at("error").as_object().at("code").is_int64());
38+
BOOST_REQUIRE_EQUAL(response.at("error").as_object().at("code").as_int64(), wrong_version.value());
39+
}
40+
41+
BOOST_AUTO_TEST_CASE(electrum__blockchain_number_of_blocks_subscribe__9_block_store__returns_9)
42+
{
43+
BOOST_REQUIRE(handshake(electrum::version::v1_0));
44+
45+
const auto response = get(R"({"id":1004,"method":"blockchain.numblocks.subscribe","params":[]})" "\n");
46+
REQUIRE_NO_THROW_TRUE(response.at("result").is_int64());
47+
BOOST_REQUIRE_EQUAL(response.at("result").as_int64(), 9);
48+
}
49+
3050
// blockchain.block.header
3151

3252
BOOST_AUTO_TEST_CASE(electrum__blockchain_block_header__insufficient_version__wrong_version)

0 commit comments

Comments
 (0)