Skip to content

Commit 93ffd47

Browse files
authored
Merge pull request libbitcoin#658 from evoskuil/master
Complete headers_subscribe and add tests.
2 parents 34d5eac + 627190f commit 93ffd47

14 files changed

Lines changed: 554 additions & 195 deletions

File tree

Makefile.am

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,12 @@ test_libbitcoin_server_test_SOURCES = \
8181
test/protocols/blocks.hpp \
8282
test/protocols/electrum/electrum.cpp \
8383
test/protocols/electrum/electrum.hpp \
84-
test/protocols/electrum/electrum_block_header.cpp \
84+
test/protocols/electrum/electrum_addresses.cpp \
85+
test/protocols/electrum/electrum_fees.cpp \
86+
test/protocols/electrum/electrum_headers.cpp \
8587
test/protocols/electrum/electrum_server.cpp \
86-
test/protocols/electrum/electrum_server_version.cpp
88+
test/protocols/electrum/electrum_server_version.cpp \
89+
test/protocols/electrum/electrum_transactions.cpp
8790

8891
endif WITH_TESTS
8992

builds/cmake/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,12 @@ if (with-tests)
310310
"../../test/protocols/blocks.hpp"
311311
"../../test/protocols/electrum/electrum.cpp"
312312
"../../test/protocols/electrum/electrum.hpp"
313-
"../../test/protocols/electrum/electrum_block_header.cpp"
313+
"../../test/protocols/electrum/electrum_addresses.cpp"
314+
"../../test/protocols/electrum/electrum_fees.cpp"
315+
"../../test/protocols/electrum/electrum_headers.cpp"
314316
"../../test/protocols/electrum/electrum_server.cpp"
315-
"../../test/protocols/electrum/electrum_server_version.cpp" )
317+
"../../test/protocols/electrum/electrum_server_version.cpp"
318+
"../../test/protocols/electrum/electrum_transactions.cpp" )
316319
317320
add_test( NAME libbitcoin-server-test COMMAND libbitcoin-server-test
318321
--run_test=*

builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,12 @@
133133
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum.cpp">
134134
<ObjectFileName>$(IntDir)test_protocols_electrum_electrum.obj</ObjectFileName>
135135
</ClCompile>
136-
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_block_header.cpp" />
136+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_addresses.cpp" />
137+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_fees.cpp" />
138+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_headers.cpp" />
137139
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_server.cpp" />
138140
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_server_version.cpp" />
141+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_transactions.cpp" />
139142
<ClCompile Include="..\..\..\..\test\settings.cpp" />
140143
<ClCompile Include="..\..\..\..\test\test.cpp">
141144
<ObjectFileName>$(IntDir)test_test.obj</ObjectFileName>

builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,13 @@
5757
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum.cpp">
5858
<Filter>src\protocols\electrum</Filter>
5959
</ClCompile>
60-
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_block_header.cpp">
60+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_addresses.cpp">
61+
<Filter>src\protocols\electrum</Filter>
62+
</ClCompile>
63+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_fees.cpp">
64+
<Filter>src\protocols\electrum</Filter>
65+
</ClCompile>
66+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_headers.cpp">
6167
<Filter>src\protocols\electrum</Filter>
6268
</ClCompile>
6369
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_server.cpp">
@@ -66,6 +72,9 @@
6672
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_server_version.cpp">
6773
<Filter>src\protocols\electrum</Filter>
6874
</ClCompile>
75+
<ClCompile Include="..\..\..\..\test\protocols\electrum\electrum_transactions.cpp">
76+
<Filter>src\protocols\electrum</Filter>
77+
</ClCompile>
6978
<ClCompile Include="..\..\..\..\test\settings.cpp">
7079
<Filter>src</Filter>
7180
</ClCompile>

include/bitcoin/server/channels/channel_electrum.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ class BCS_API channel_electrum
6565
return name_;
6666
}
6767

68-
inline void set_version(electrum::version version) NOEXCEPT
68+
inline void set_version(server::electrum::version version) NOEXCEPT
6969
{
7070
version_ = version;
7171
}
7272

73-
inline electrum::version version() const NOEXCEPT
73+
inline server::electrum::version version() const NOEXCEPT
7474
{
7575
return version_;
7676
}
@@ -85,7 +85,7 @@ class BCS_API channel_electrum
8585
const options_t& options_;
8686

8787
// These are protected by strand.
88-
electrum::version version_{ electrum::version::v0_0 };
88+
server::electrum::version version_{ server::electrum::version::v0_0 };
8989
std::string name_{};
9090
};
9191

include/bitcoin/server/protocols/protocol_electrum.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ class BCS_API protocol_electrum
128128
void blockchain_block_headers(size_t starting, size_t quantity,
129129
size_t waypoint, bool multiplicity) NOEXCEPT;
130130

131-
inline bool is_version(electrum::version version) const NOEXCEPT
131+
/// Notify client of new header.
132+
void do_header(node::header_t link) NOEXCEPT;
133+
134+
inline bool is_version(server::electrum::version version) const NOEXCEPT
132135
{
133136
return channel_->version() >= version;
134137
}
@@ -139,8 +142,9 @@ class BCS_API protocol_electrum
139142
}
140143

141144
private:
142-
// This is thread safe.
145+
// These are thread safe.
143146
const options_t& options_;
147+
std::atomic_bool subscribed_{};
144148

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

src/protocols/protocol_electrum.cpp

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,22 @@ void protocol_electrum::stopping(const code& ec) NOEXCEPT
9494
// ----------------------------------------------------------------------------
9595

9696
bool protocol_electrum::handle_event(const code&, node::chase event_,
97-
node::event_value) NOEXCEPT
97+
node::event_value value) NOEXCEPT
9898
{
9999
// Do not pass ec to stopped as it is not a call status.
100100
if (stopped())
101101
return false;
102102

103103
switch (event_)
104104
{
105-
case node::chase::suspend:
105+
case node::chase::organized:
106106
{
107+
if (subscribed_.load(std::memory_order_relaxed))
108+
{
109+
BC_ASSERT(std::holds_alternative<node::header_t>(value));
110+
POST(do_header, std::get<node::header_t>(value));
111+
}
112+
107113
break;
108114
}
109115
default:
@@ -297,19 +303,39 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec,
297303
return;
298304
}
299305

300-
// TODO: signal header subscription.
306+
subscribed_.store(true, std::memory_order_relaxed);
307+
send_result(
308+
{
309+
object_t
310+
{
311+
{ "height", uint64_t{ top } },
312+
{ "hex", to_hex(*header, chain::header::serialized_size()) }
313+
}
314+
}, 256, BIND(complete, _1));
315+
}
301316

302-
// TODO: idempotent subscribe to chase::organized via session/chaser/node.
303-
// TODO: upon notification send just the header notified by the link.
304-
// TODO: it is client responsibility to deal with reorgs and race gaps.
305-
send_result(value_t
317+
void protocol_electrum::do_header(node::header_t link) NOEXCEPT
318+
{
319+
BC_ASSERT(stranded());
320+
321+
const auto& query = archive();
322+
const auto height = query.get_height(link);
323+
const auto header = query.get_header(link);
324+
325+
if (height.is_terminal() || !header)
326+
{
327+
LOGF("Electrum::do_header, object not found (" << link << ").");
328+
return;
329+
}
330+
331+
send_notification("blockchain.headers.subscribe",
332+
{
333+
object_t
306334
{
307-
object_t
308-
{
309-
{ "height", uint64_t{ top } },
310-
{ "hex", to_hex(*header, chain::header::serialized_size()) }
311-
}
312-
}, 256, BIND(complete, _1));
335+
{ "height", height.value },
336+
{ "hex", to_hex(*header, chain::header::serialized_size()) }
337+
}
338+
}, 100, BIND(complete, _1));
313339
}
314340

315341
void protocol_electrum::handle_blockchain_estimate_fee(const code& ec,
@@ -381,6 +407,8 @@ void protocol_electrum::handle_blockchain_scripthash_unsubscribe(const code& ec,
381407
send_code(error::not_implemented);
382408
}
383409

410+
// TODO: requires tx pool in order to validate against unconfirmed txs.
411+
// TODO: requires that p2p channels subscribe to transaction broadcast.
384412
void protocol_electrum::handle_blockchain_transaction_broadcast(const code& ec,
385413
rpc_interface::blockchain_transaction_broadcast,
386414
const std::string& ) NOEXCEPT
@@ -477,14 +505,14 @@ void protocol_electrum::handle_mempool_get_fee_histogram(const code& ec,
477505

478506
// TODO: requires tx pool metadata graph.
479507
send_result(value_t
508+
{
509+
array_t
480510
{
481-
array_t
482-
{
483-
array_t{ 1, 1024 },
484-
array_t{ 2, 2048 },
485-
array_t{ 4, 4096 }
486-
}
487-
}, 256, BIND(complete, _1));
511+
array_t{ 1, 1024 },
512+
array_t{ 2, 2048 },
513+
array_t{ 4, 4096 }
514+
}
515+
}, 256, BIND(complete, _1));
488516
}
489517

490518
BC_POP_WARNING()

test/protocols/blocks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ const chain::block block5{ block5_data, true };
7575
const chain::block block6{ block6_data, true };
7676
const chain::block block7{ block7_data, true };
7777
const chain::block block8{ block8_data, true };
78-
const chain::block block9{ block8_data, true };
78+
const chain::block block9{ block9_data, true };
7979

8080
const server::settings::embedded_pages admin{};
8181
const server::settings::embedded_pages native{};

test/protocols/electrum/electrum.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ electrum_setup_fixture::electrum_setup_fixture()
5252
electrum.connections = 1;
5353
database_settings.interval_depth = 2;
5454
node_settings.delay_inbound = false;
55+
node_settings.minimum_fee_rate = 99.0;
5556
network_settings.inbound.connections = 0;
5657
network_settings.outbound.connections = 0;
5758
auto ec = store_.create([](auto, auto) {});
@@ -127,4 +128,4 @@ bool electrum_setup_fixture::handshake(const std::string& version,
127128
(result.at(0).is_string() && result.at(1).is_string()) &&
128129
(result.at(0).as_string() == config().server.electrum.server_name) &&
129130
(result.at(1).as_string() == version);
130-
}
131+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (c) 2011-2026 libbitcoin developers (see AUTHORS)
3+
*
4+
* This file is part of libbitcoin.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
#include "../../test.hpp"
20+
#include "electrum.hpp"
21+
22+
BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_setup_fixture)
23+
24+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)