Skip to content

Commit b549c9f

Browse files
authored
Merge pull request #772 from evoskuil/master
Narrow scope of reorganization lock to just get fork.
2 parents 591a415 + 8d5d7dd commit b549c9f

File tree

6 files changed

+44
-33
lines changed

6 files changed

+44
-33
lines changed

include/bitcoin/node/chasers/chaser.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class BCN_API chaser
9494
virtual code reload(const store::event_handler& handler) NOEXCEPT;
9595

9696
/// Get reorganization lock.
97-
virtual lock get_reorganization_lock() NOEXCEPT;
97+
virtual lock get_reorganization_lock() const NOEXCEPT;
9898

9999
/// Events.
100100
/// -----------------------------------------------------------------------

include/bitcoin/node/chasers/chaser_confirm.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ class BCN_API chaser_confirm
7070
size_t top) NOEXCEPT;
7171

7272
// getters
73-
bool get_fork_work(uint256_t& fork_work, header_links& fork,
74-
height_t fork_top) const NOEXCEPT;
75-
bool get_is_strong(bool& strong, const uint256_t& fork_work,
73+
header_links get_fork(height_t fork_top) const NOEXCEPT;
74+
bool get_work(uint256_t& fork_work,
75+
const header_links& fork) const NOEXCEPT;
76+
bool get_strong(bool& strong, const uint256_t& fork_work,
7677
size_t fork_point) const NOEXCEPT;
7778
};
7879

include/bitcoin/node/full_node.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class BCN_API full_node
141141

142142
/// Get reorganization lock.
143143
/// Used to prevent candidate chain reorganization during confirmation.
144-
virtual lock get_reorganization_lock() NOEXCEPT;
144+
virtual lock get_reorganization_lock() const NOEXCEPT;
145145

146146
protected:
147147
/// Session attachments.
@@ -164,8 +164,8 @@ class BCN_API full_node
164164
event_value value) NOEXCEPT;
165165

166166
// These are thread safe.
167+
mutable std::mutex reorganization_mutex_{};
167168
const configuration& config_;
168-
std::mutex reorganization_mutex_{};
169169
memory_controller memory_;
170170
query& query_;
171171

src/chasers/chaser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ code chaser::reload(const store::event_handler& handler) NOEXCEPT
8383
return node_.reload(handler);
8484
}
8585

86-
lock chaser::get_reorganization_lock() NOEXCEPT
86+
lock chaser::get_reorganization_lock() const NOEXCEPT
8787
{
8888
return node_.get_reorganization_lock();
8989
}

src/chasers/chaser_confirm.cpp

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -159,25 +159,21 @@ void chaser_confirm::do_bumped(height_t height) NOEXCEPT
159159
if (closed())
160160
return;
161161

162-
// Prevents organizer from popping candidates (does not block push).
163-
get_reorganization_lock();
162+
// If empty height is not on a candidate fork (may have been reorganized).
163+
auto fork = get_fork(height);
164+
if (fork.empty())
165+
return;
164166

165-
// Scan from candidate height to first confirmed, return links and work.
166167
uint256_t work{};
167-
header_links fork{};
168-
if (!get_fork_work(work, fork, height))
168+
if (!get_work(work, fork))
169169
{
170170
fault(error::confirm1);
171171
return;
172172
}
173173

174-
// No longer a candidate fork (may have been reorganized).
175-
if (fork.empty())
176-
return;
177-
178174
bool strong{};
179175
const auto fork_point = height - fork.size();
180-
if (!get_is_strong(strong, work, fork_point))
176+
if (!get_strong(strong, work, fork_point))
181177
{
182178
fault(error::confirm2);
183179
return;
@@ -427,42 +423,56 @@ bool chaser_confirm::roll_back(const header_links& popped, size_t fork_point,
427423

428424
// Private getters
429425
// ----------------------------------------------------------------------------
430-
// These are subject to intervening/concurrent candidate chain reorganization.
431426

432-
bool chaser_confirm::get_fork_work(uint256_t& fork_work, header_links& fork,
427+
// TODO: move into database library with internal lock.
428+
chaser_confirm::header_links chaser_confirm::get_fork(
433429
height_t fork_top) const NOEXCEPT
434430
{
435431
BC_ASSERT(stranded());
436432
const auto& query = archive();
437433
header_link link{};
438-
fork_work = zero;
439-
fork.clear();
434+
header_links out{};
435+
436+
// Prevents organizer from popping candidates (does not block push).
437+
get_reorganization_lock();
440438

441439
// Walk down candidates from fork_top to fork point (highest common).
442-
for (link = query.to_candidate(fork_top); !link.is_terminal() &&
443-
!query.is_confirmed_block(link); link = query.to_candidate(--fork_top))
440+
for (link = query.to_candidate(fork_top);
441+
!link.is_terminal() && !query.is_confirmed_block(link);
442+
link = query.to_candidate(--fork_top))
444443
{
445-
uint32_t bits{};
446-
if (!query.get_bits(bits, link))
447-
return false;
448-
449-
fork_work += chain::header::proof(bits);
450-
fork.push_back(link);
444+
out.push_back(link);
451445
}
452446

453447
// Terminal candidate from previously valid height implies regression.
454448
// This is ok, it just means that the fork is no longer a candidate.
455449
if (link.is_terminal())
450+
out.clear();
451+
452+
return out;
453+
}
454+
455+
bool chaser_confirm::get_work(uint256_t& fork_work,
456+
const header_links& fork) const NOEXCEPT
457+
{
458+
BC_ASSERT(stranded());
459+
const auto& query = archive();
460+
461+
// Walk down candidates from fork_top to fork point (highest common).
462+
for (const auto& link: fork)
456463
{
457-
fork_work = zero;
458-
fork.clear();
464+
uint32_t bits{};
465+
if (!query.get_bits(bits, link))
466+
return false;
467+
468+
fork_work += chain::header::proof(bits);
459469
}
460470

461471
return true;
462472
}
463473

464474
// A fork with greater work will cause confirmed reorganization.
465-
bool chaser_confirm::get_is_strong(bool& strong, const uint256_t& fork_work,
475+
bool chaser_confirm::get_strong(bool& strong, const uint256_t& fork_work,
466476
size_t fork_point) const NOEXCEPT
467477
{
468478
BC_ASSERT(stranded());

src/full_node.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ network::memory& full_node::get_memory() NOEXCEPT
370370
return memory_;
371371
}
372372

373-
lock full_node::get_reorganization_lock() NOEXCEPT
373+
lock full_node::get_reorganization_lock() const NOEXCEPT
374374
{
375375
return lock{ reorganization_mutex_ };
376376
}

0 commit comments

Comments
 (0)