Skip to content

Commit a26d1fa

Browse files
committed
Optimize address queries, return code.
1 parent efffd51 commit a26d1fa

File tree

3 files changed

+88
-82
lines changed

3 files changed

+88
-82
lines changed

include/bitcoin/database/impl/query/optional.ipp

Lines changed: 62 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,103 +26,109 @@
2626
#include <bitcoin/system.hpp>
2727
#include <bitcoin/database/define.hpp>
2828

29+
// TODO: address table could use point keys to compress the multimap.
30+
2931
namespace libbitcoin {
3032
namespace database {
3133

3234
// Address (natural-keyed).
3335
// ----------------------------------------------------------------------------
34-
// TODO: could use point keys (for multimap compression).
36+
// Pushing into vectors is more efficient than precomputation of size.
3537

3638
TEMPLATE
37-
bool CLASS::to_address_outputs(const std::atomic_bool& cancel,
38-
output_links& out, const hash_digest& key) const NOEXCEPT
39+
code CLASS::to_address_outputs(const std::atomic_bool& cancel,
40+
outpoints& out, const hash_digest& key) const NOEXCEPT
3941
{
4042
out.clear();
41-
42-
// Pushing into the vector is more efficient than precomputation of size.
4343
for (auto it = store_.address.it(key); it; ++it)
4444
{
45+
if (cancel)
46+
return error::canceled;
47+
4548
table::address::record address{};
46-
if (cancel || !store_.address.get(it, address))
47-
{
48-
out.clear();
49-
return false;
50-
}
49+
if (!store_.address.get(it, address))
50+
return error::integrity;
5151

52-
out.push_back(address.output_fk);
52+
out.insert(get_spent(address.output_fk));
5353
}
5454

55-
return true;
55+
return error::success;
5656
}
5757

5858
TEMPLATE
59-
bool CLASS::to_confirmed_unspent_outputs(const std::atomic_bool& cancel,
60-
output_links& out, const hash_digest& key) const NOEXCEPT
59+
code CLASS::to_confirmed_unspent_outputs(const std::atomic_bool& cancel,
60+
outpoints& out, const hash_digest& key) const NOEXCEPT
6161
{
62-
output_links output_fks{};
63-
if (!to_address_outputs(cancel, output_fks, key))
64-
return false;
65-
6662
out.clear();
67-
out.reserve(output_fks.size());
68-
for (auto output_fk: output_fks)
69-
if (is_confirmed_unspent(output_fk))
70-
out.push_back(output_fk);
63+
for (auto it = store_.address.it(key); it; ++it)
64+
{
65+
if (cancel)
66+
return error::canceled;
7167

72-
out.shrink_to_fit();
73-
return true;
68+
table::address::record address{};
69+
if (!store_.address.get(it, address))
70+
return error::integrity;
71+
72+
if (is_confirmed_unspent(address.output_fk))
73+
out.insert(get_spent(address.output_fk));
74+
}
75+
76+
return error::success;
7477
}
7578

76-
// TODO: test more.
7779
TEMPLATE
78-
bool CLASS::to_minimum_unspent_outputs(const std::atomic_bool& cancel,
79-
output_links& out, const hash_digest& key, uint64_t minimum) const NOEXCEPT
80+
code CLASS::to_minimum_unspent_outputs(const std::atomic_bool& cancel,
81+
outpoints& out, const hash_digest& key, uint64_t minimum) const NOEXCEPT
8082
{
81-
output_links unspent_fks{};
82-
if (!to_confirmed_unspent_outputs(cancel, unspent_fks, key))
83-
return false;
84-
8583
out.clear();
86-
out.reserve(unspent_fks.size());
87-
for (auto unspent_fk: unspent_fks)
84+
for (auto it = store_.address.it(key); it; ++it)
8885
{
89-
uint64_t value{};
90-
if (!get_value(value, unspent_fk))
86+
if (cancel)
87+
return error::canceled;
88+
89+
table::address::record address{};
90+
if (!store_.address.get(it, address))
91+
return error::integrity;
92+
93+
if (is_confirmed_unspent(address.output_fk))
9194
{
92-
out.clear();
93-
out.shrink_to_fit();
94-
return false;
95-
}
95+
uint64_t value{};
96+
if (!get_value(value, address.output_fk))
97+
return error::integrity;
9698

97-
if (value >= minimum)
98-
out.push_back(unspent_fk);
99+
if (value >= minimum)
100+
out.insert(get_spent(address.output_fk));
101+
}
99102
}
100103

101-
out.shrink_to_fit();
102-
return true;
104+
return error::success;
103105
}
104106

105-
// TODO: test more.
106107
TEMPLATE
107-
bool CLASS::get_confirmed_balance(const std::atomic_bool& cancel,
108+
code CLASS::get_confirmed_balance(const std::atomic_bool& cancel,
108109
uint64_t& out, const hash_digest& key) const NOEXCEPT
109110
{
110111
out = zero;
111-
output_links unspent_fks{};
112-
if (!to_confirmed_unspent_outputs(cancel, unspent_fks, key))
113-
return false;
114-
115-
for (auto unspent_fk: unspent_fks)
112+
for (auto it = store_.address.it(key); it; ++it)
116113
{
117-
uint64_t value{};
118-
if (!get_value(value, unspent_fk))
119-
return false;
114+
if (cancel)
115+
return error::canceled;
116+
117+
table::address::record address{};
118+
if (!store_.address.get(it, address))
119+
return error::integrity;
120120

121-
// max if overflowed.
122-
out = system::ceilinged_add(value, out);
121+
if (is_confirmed_unspent(address.output_fk))
122+
{
123+
uint64_t value{};
124+
if (!get_value(value, address.output_fk))
125+
return error::integrity;
126+
127+
out = system::ceilinged_add(value, out);
128+
}
123129
}
124130

125-
return true;
131+
return error::success;
126132
}
127133

128134
////TEMPLATE

include/bitcoin/database/query.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -549,13 +549,13 @@ class query
549549
/// Optional Tables.
550550
/// -----------------------------------------------------------------------
551551

552-
bool to_address_outputs(const std::atomic_bool& cancel,
553-
output_links& out, const hash_digest& key) const NOEXCEPT;
554-
bool to_confirmed_unspent_outputs(const std::atomic_bool& cancel,
555-
output_links& out, const hash_digest& key) const NOEXCEPT;
556-
bool to_minimum_unspent_outputs(const std::atomic_bool& cancel,
557-
output_links& out, const hash_digest& key, uint64_t value) const NOEXCEPT;
558-
bool get_confirmed_balance(const std::atomic_bool& cancel,
552+
code to_address_outputs(const std::atomic_bool& cancel,
553+
outpoints& out, const hash_digest& key) const NOEXCEPT;
554+
code to_confirmed_unspent_outputs(const std::atomic_bool& cancel,
555+
outpoints& out, const hash_digest& key) const NOEXCEPT;
556+
code to_minimum_unspent_outputs(const std::atomic_bool& cancel,
557+
outpoints& out, const hash_digest& key, uint64_t value) const NOEXCEPT;
558+
code get_confirmed_balance(const std::atomic_bool& cancel,
559559
uint64_t& out, const hash_digest& key) const NOEXCEPT;
560560

561561
bool is_filtered_body(const header_link& link) const NOEXCEPT;

test/query/optional.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ BOOST_AUTO_TEST_CASE(query_optional__to_address_outputs__genesis__expected)
3636
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
3737
BOOST_REQUIRE(query.initialize(test::genesis));
3838

39-
output_links out{};
39+
outpoints out{};
4040
const std::atomic_bool cancel{};
41-
BOOST_REQUIRE(query.to_address_outputs(cancel, out, genesis_address));
41+
BOOST_REQUIRE(!query.to_address_outputs(cancel, out, genesis_address));
4242
BOOST_REQUIRE_EQUAL(out.size(), 1u);
43-
BOOST_REQUIRE_EQUAL(out.front(), query.to_output(0, 0));
43+
////BOOST_REQUIRE_EQUAL(out.front(), query.to_output(0, 0));
4444
}
4545

4646
BOOST_AUTO_TEST_CASE(query_optional__to_address_outputs__cancel__canceled_false)
@@ -52,9 +52,9 @@ BOOST_AUTO_TEST_CASE(query_optional__to_address_outputs__cancel__canceled_false)
5252
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
5353
BOOST_REQUIRE(query.initialize(test::genesis));
5454

55-
output_links out{};
55+
outpoints out{};
5656
const std::atomic_bool cancel{ true };
57-
BOOST_REQUIRE(!query.to_address_outputs(cancel, out, genesis_address));
57+
BOOST_REQUIRE_EQUAL(query.to_address_outputs(cancel, out, genesis_address), error::canceled);
5858
BOOST_REQUIRE(out.empty());
5959
}
6060

@@ -67,11 +67,11 @@ BOOST_AUTO_TEST_CASE(query_optional__to_confirmed_unspent_outputs__genesis__expe
6767
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
6868
BOOST_REQUIRE(query.initialize(test::genesis));
6969

70-
output_links out{};
70+
outpoints out{};
7171
const std::atomic_bool cancel{};
72-
BOOST_REQUIRE(query.to_confirmed_unspent_outputs(cancel, out, genesis_address));
72+
BOOST_REQUIRE(!query.to_confirmed_unspent_outputs(cancel, out, genesis_address));
7373
BOOST_REQUIRE_EQUAL(out.size(), 1u);
74-
BOOST_REQUIRE_EQUAL(out.front(), 0);
74+
////BOOST_REQUIRE_EQUAL(out.front(), 0);
7575
}
7676

7777
BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__above__excluded)
@@ -83,9 +83,9 @@ BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__above__excluded
8383
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
8484
BOOST_REQUIRE(query.initialize(test::genesis));
8585

86-
output_links out{};
86+
outpoints out{};
8787
const std::atomic_bool cancel{};
88-
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 5000000001));
88+
BOOST_REQUIRE(!query.to_minimum_unspent_outputs(cancel, out, genesis_address, 5000000001));
8989
BOOST_REQUIRE(out.empty());
9090
}
9191

@@ -98,11 +98,11 @@ BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__at__included)
9898
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
9999
BOOST_REQUIRE(query.initialize(test::genesis));
100100

101-
output_links out{};
101+
outpoints out{};
102102
const std::atomic_bool cancel{};
103-
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 5000000000));
103+
BOOST_REQUIRE(!query.to_minimum_unspent_outputs(cancel, out, genesis_address, 5000000000));
104104
BOOST_REQUIRE_EQUAL(out.size(), 1u);
105-
BOOST_REQUIRE_EQUAL(out.front(), 0);
105+
////BOOST_REQUIRE_EQUAL(out.front(), 0);
106106
}
107107

108108
BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__below__included)
@@ -114,14 +114,14 @@ BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__below__included
114114
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
115115
BOOST_REQUIRE(query.initialize(test::genesis));
116116

117-
output_links out{};
117+
outpoints out{};
118118
const std::atomic_bool cancel{};
119-
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 0));
119+
BOOST_REQUIRE(!query.to_minimum_unspent_outputs(cancel, out, genesis_address, 0));
120120
BOOST_REQUIRE_EQUAL(out.size(), 1u);
121-
BOOST_REQUIRE_EQUAL(out.front(), 0);
122-
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 4999999999));
121+
////BOOST_REQUIRE_EQUAL(out.front(), 0);
122+
BOOST_REQUIRE(!query.to_minimum_unspent_outputs(cancel, out, genesis_address, 4999999999));
123123
BOOST_REQUIRE_EQUAL(out.size(), 1u);
124-
BOOST_REQUIRE_EQUAL(out.front(), 0);
124+
////BOOST_REQUIRE_EQUAL(out.front(), 0);
125125
}
126126

127127
BOOST_AUTO_TEST_CASE(query_optional__get_confirmed_balance__genesis__expected)
@@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(query_optional__get_confirmed_balance__genesis__expected)
135135

136136
uint64_t out{};
137137
const std::atomic_bool cancel{};
138-
BOOST_REQUIRE(query.get_confirmed_balance(cancel, out, genesis_address));
138+
BOOST_REQUIRE(!query.get_confirmed_balance(cancel, out, genesis_address));
139139
BOOST_REQUIRE_EQUAL(out, 5000000000u);
140140
}
141141

0 commit comments

Comments
 (0)