Skip to content

Commit

Permalink
Merge pull request #639 from evoskuil/master
Browse files Browse the repository at this point in the history
Update confirmation and validation chasers.
  • Loading branch information
evoskuil authored Jun 5, 2024
2 parents fa392c0 + 5310ea4 commit 6c9d69b
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 90 deletions.
6 changes: 2 additions & 4 deletions include/bitcoin/node/chasers/chaser_confirm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,10 @@ class BCN_API chaser_confirm

virtual void do_bypass(size_t height) NOEXCEPT;
virtual void do_validated(height_t height) NOEXCEPT;
virtual code confirm(const database::header_link& link,
size_t height) NOEXCEPT;

private:
bool set_confirmed(header_t link, height_t height) NOEXCEPT;
bool set_unconfirmed(header_t link, height_t height) NOEXCEPT;
bool set_organized(header_t link, height_t height) NOEXCEPT;
bool set_reorganized(header_t link, height_t height) NOEXCEPT;
bool roll_back(const header_links& popped,
size_t fork_point, size_t top) NOEXCEPT;
bool get_fork_work(uint256_t& fork_work, header_links& fork,
Expand Down
124 changes: 55 additions & 69 deletions src/chasers/chaser_confirm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,10 @@ void chaser_confirm::do_validated(height_t height) NOEXCEPT
if (closed())
return;

// TODO: update specialized fault codes.

// Compute relative work.
// ........................................................................
// A reorg race may have resulted in height not now being a candidate.

bool strong{};
uint256_t work{};
Expand All @@ -129,7 +130,6 @@ void chaser_confirm::do_validated(height_t height) NOEXCEPT
return;
}

// Nothing to do. In this case candidate top is/was above height.
if (!strong)
return;

Expand Down Expand Up @@ -179,117 +179,103 @@ void chaser_confirm::do_validated(height_t height) NOEXCEPT
// Confirm block.
// ....................................................................

if (const auto code = confirm(link, index))
auto ec = query.get_block_state(link);
if (ec == database::error::integrity)
{
if (code == error::confirmation_bypass ||
code == database::error::block_confirmable)
{
// Advance and confirm.
notify(code, chase::confirmable, index);
fire(events::confirm_bypassed, index);
fault(ec);
return;
}

if (ec == database::error::block_unconfirmable)
{
notify(ec, chase::unconfirmable, link);
fire(events::block_unconfirmable, index);
return;
}

const auto malleable64 = query.is_malleable64(link);

// chase::organized & events::block_organized
if (!set_confirmed(link, index++))
// error::confirmation_bypass is not used.
if (ec == database::error::block_confirmable ||
(is_under_bypass(index) && !malleable64))
{
notify(ec, chase::confirmable, index);
fire(events::confirm_bypassed, index);
continue;
}

ec = query.block_confirmable(link);
if (ec == database::error::integrity)
{
fault(error::node_confirm);
return;
}

if (ec)
{
// Transactions are set strong upon archive when under bypass.
if (is_under_bypass(height))
{
if (!query.set_unstrong(link))
{
fault(error::set_confirmed);
fault(error::node_confirm);
return;
}

continue;
}

if (code == error::store_integrity)
{
fault(error::node_confirm);
return;
}

if (query.is_malleable64(link))
{
// Index will be reported multiple times when 'height' is above.
notify(code, chase::malleated, link);
// Must be malleable64 if validated when under bypass.
LOGR("Malleated64 block [" << index << "] " << ec.message());
notify(ec, chase::malleated, link);
fire(events::block_malleated, index);
return;
}

if (code != database::error::block_unconfirmable &&
!query.set_block_unconfirmable(link))
if (!query.set_block_unconfirmable(link))
{
fault(error::set_block_unconfirmable);
return;
}

// Index will be reported multiple times when 'height' is above.
notify(code, chase::unconfirmable, link);
LOGR("Unconfirmable block [" << index << "] " << ec.message());
notify(ec, chase::unconfirmable, link);
fire(events::block_unconfirmable, index);

// chase::reorganized & events::block_reorganized
// chase::organized & events::block_organized
if (!roll_back(popped, fork_point, sub1(index)))
if (!roll_back(popped, fork_point, index))
{
fault(error::node_roll_back);
return;
}

LOGR("Unconfirmable block [" << index << "] " << code.message());

return;
}

// Commit confirmation metadata.
// ....................................................................

// TODO: compute fees from validation records (optional metadata).
if (!query.set_block_confirmable(link, uint64_t{}))
{
fault(error::block_confirmable);
return;
}

// Advance and confirm.
// ....................................................................

notify(error::success, chase::confirmable, index);
fire(events::block_confirmed, index);

// chase::organized & events::block_organized
if (!set_confirmed(link, index++))
if (!set_organized(link, index))
{
fault(error::set_confirmed);
return;
}

LOGV("Block confirmed: " << height);
LOGV("Block confirmed and organized: " << index);
++index;
}
}

code chaser_confirm::confirm(const header_link& link, size_t height) NOEXCEPT
{
auto& query = archive();

// All blocks must be set_strong.
if (!query.set_strong(link))
return error::store_integrity;

// query.is_malleable64(link) is used when there is no block instance.
if (is_under_bypass(height) && !query.is_malleable64(link))
return error::confirmation_bypass;

const auto ec = query.get_block_state(link);
if (ec == database::error::block_confirmable ||
ec == database::error::block_unconfirmable)
return ec;

if (ec == database::error::block_valid)
return error::success;

// Should not get here without a known block state.
return error::store_integrity;
}

// Private
// ----------------------------------------------------------------------------

bool chaser_confirm::set_confirmed(header_t link, height_t height) NOEXCEPT
bool chaser_confirm::set_organized(header_t link, height_t height) NOEXCEPT
{
auto& query = archive();
if (!query.push_confirmed(link))
Expand All @@ -300,7 +286,7 @@ bool chaser_confirm::set_confirmed(header_t link, height_t height) NOEXCEPT
return true;
}

bool chaser_confirm::set_unconfirmed(header_t link, height_t height) NOEXCEPT
bool chaser_confirm::set_reorganized(header_t link, height_t height) NOEXCEPT
{
auto& query = archive();
if (!query.set_unstrong(link) || !query.pop_confirmed())
Expand All @@ -315,12 +301,12 @@ bool chaser_confirm::roll_back(const header_links& popped,
size_t fork_point, size_t top) NOEXCEPT
{
auto& query = archive();
for (auto height = add1(fork_point); height <= top; ++height)
if (!set_unconfirmed(query.to_confirmed(height), height))
for (auto height = top; height > fork_point; --height)
if (!set_reorganized(query.to_confirmed(height), height))
return false;

for (const auto& link: views_reverse(popped))
if (!query.set_strong(link) || !set_confirmed(link, ++fork_point))
if (!query.set_strong(link) || !set_organized(link, ++fork_point))
return false;

return true;
Expand Down
38 changes: 21 additions & 17 deletions src/chasers/chaser_validate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ void chaser_validate::do_bump(height_t) NOEXCEPT
BC_ASSERT(stranded());
const auto& query = archive();

// TODO: update specialized fault codes.

// Validate checked blocks starting immediately after last validated.
for (auto height = add1(position()); !closed(); ++height)
{
Expand All @@ -158,17 +160,19 @@ void chaser_validate::do_bump(height_t) NOEXCEPT

if (ec == database::error::integrity)
{
fault(ec);
fault(error::node_validate);
return;
}

if (ec == database::error::block_unconfirmable)
{
notify(ec, chase::unconfirmable, height);
LOGR("Unconfirmable block [" << height << "] " << ec.message());
notify(ec, chase::unvalid, link);
fire(events::block_unconfirmable, height);
return;
}

// error::validation_bypass is not used because fan-out.
if (ec == database::error::block_valid ||
ec == database::error::block_confirmable ||
(is_under_bypass(height) && !query.is_malleable64(link)))
Expand All @@ -183,7 +187,7 @@ void chaser_validate::do_bump(height_t) NOEXCEPT
// This will very rapidly pump all outstanding work into asio queue.
if (!enqueue_block(link))
{
fault(error::store_integrity);
fault(error::node_validate);
return;
}

Expand Down Expand Up @@ -308,7 +312,7 @@ void chaser_validate::handle_tx(const code& ec, const tx_link& tx,
// handle_txs will only get invoked once, with a first error code, so
// invoke fault here ensure that non-validation codes are not lost.
if (ec == error::store_integrity || ec == database::error::integrity)
fault(ec);
fault(error::node_validate);

// TODO: need to sort out bypass, validity, and fault codes.
// Always allow the racer to finish, invokes handle_txs exactly once.
Expand Down Expand Up @@ -338,30 +342,28 @@ void chaser_validate::validate_block(const code& ec,
const header_link& link, const database::context& ctx) NOEXCEPT
{
BC_ASSERT(stranded());
auto& query = archive();

if (ec)
{
const auto malleable64 = query.is_malleable64(link);
auto& query = archive();

// Must be malleable64 if failed under checkpoint.
// Transactions are set strong upon archive when under bypass.
if (is_under_bypass(ctx.height) &&
(!malleable64 || query.set_unstrong(link)))
if (is_under_bypass(ctx.height))
{
fault(error::store_integrity);
return;
}

if (malleable64)
{
// TODO: log malleated64 block with ec.
if (!query.set_unstrong(link))
{
fault(error::node_validate);
return;
}

// Must be malleable64 if validated when under bypass.
LOGR("Malleated64 block [" << ctx.height << "] " << ec.message());
notify(ec, chase::malleated, link);
fire(events::block_malleated, ctx.height);
return;
}

// TODO: log block is unconfirmable.
LOGR("Unconfirmable block [" << ctx.height << "] " << ec.message());
notify(ec, chase::unconfirmable, link);
fire(events::block_unconfirmable, ctx.height);
return;
Expand All @@ -373,6 +375,8 @@ void chaser_validate::validate_block(const code& ec,
// fire event first so that log is ordered.
fire(events::block_validated, ctx.height);
notify(ec, chase::valid, ctx.height);

LOGV("Block.txs accepted and connected: " << ctx.height);
}

// neutrino
Expand Down

0 comments on commit 6c9d69b

Please sign in to comment.