@@ -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 ());
0 commit comments