diff --git a/console/executor_store.cpp b/console/executor_store.cpp index d0d2b95ef..c41a3859e 100644 --- a/console/executor_store.cpp +++ b/console/executor_store.cpp @@ -236,6 +236,7 @@ bool executor::hot_backup_store(bool details) full_node::store::tables.at(table)); })) { + // system::error::not_a_stream when disk is full. logger(format(BN_NODE_BACKUP_FAIL) % ec.message()); return false; } @@ -258,6 +259,7 @@ bool executor::cold_backup_store(bool details) full_node::store::tables.at(table)); })) { + // system::error::not_a_stream when disk is full. logger(format(BN_NODE_BACKUP_FAIL) % ec.message()); return false; } diff --git a/console/executor_test_reader.cpp b/console/executor_test_reader.cpp index f67b5d0ef..418f05284 100644 --- a/console/executor_test_reader.cpp +++ b/console/executor_test_reader.cpp @@ -41,6 +41,7 @@ using namespace std::chrono; using namespace std::placeholders; // arbitrary testing (const). + void executor::read_test(bool dump) const { using namespace database; @@ -809,18 +810,29 @@ void executor::read_test(bool dump) const logger(format("STOP (%1% secs)") % span.count()); } - // TODO: create a block/tx dumper. void executor::read_test(bool) const { - constexpr auto hash511280 = base16_hash( - "00000000000000000030b12ee5a31aaf553f49cdafa52698f70f0f0706f46d3d"); - + constexpr auto link = 600'000_size; const auto start = logger::now(); - const auto link = query_.to_header(hash511280); - if (link.is_terminal()) + + const auto height = query_.get_height(link); + if (height.is_terminal()) + { + logger("height.is_terminal()"); + return; + } + + if (height != link) + { + logger("height != link"); + return; + } + + code ec{}; + if ((ec = query_.block_confirmable(link))) { - logger("link.is_terminal()"); + logger(format("query_.block_confirmable: %1%") % ec.message()); return; } @@ -855,24 +867,36 @@ void executor::read_test(bool) const state.timestamp = block->header().timestamp(); state.minimum_block_version = 0; state.work_required = 0; + + if (!block->populate(state)) + { + logger("!block->populate(state)"); + return; + } + if (!query_.populate(*block)) { logger("!query_.populate(*block)"); return; } - code ec{}; if ((ec = block->check())) { - logger(format("Block check: %1%") % ec.message()); + logger(format("Block check(): %1%") % ec.message()); + return; + } + + if ((ec = block->check(state))) + { + logger(format("Block check(state): %1%") % ec.message()); return; } - const auto& coin = metadata_.configured.bitcoin; - if ((ec = block->accept(state, coin.subsidy_interval_blocks, - coin.initial_subsidy()))) + if ((ec = block->accept(state, + metadata_.configured.bitcoin.subsidy_interval_blocks, + metadata_.configured.bitcoin.initial_subsidy()))) { - logger(format("Block accept: %1%") % ec.message()); + logger(format("Block accept(state): %1%") % ec.message()); return; } @@ -882,8 +906,39 @@ void executor::read_test(bool) const return; } + logger(format("segregated [%1%]") % to_int(block->is_segregated())); + logger(format("segregated count [%1%]") % block->segregated()); + const auto span = duration_cast(logger::now() - start); - logger(format("Validated block 511280 in %1% msec.") % span.count()); + logger(format("Validated block [%1%] in %2% msec.") % link % span.count()); + + ////constexpr auto tx_hash = base16_hash( + //// "eb2179db6c40bceb02cebcc5c99cf783ed6385b00767c7a5419fe530eaba8bff"); + ////const auto tx_link = query_.to_tx(tx_hash); + ////const auto tx = query_.get_transaction(tx_link); + ////const auto result = query_.populate(*tx); + ////const auto size = tx->serialized_size(false); + ////const auto weight = tx->serialized_size(true); + ////const auto version = tx->version(); + ////const auto locktime = tx->locktime(); + ////const auto fee = tx->fee(); + ////const auto sequence = tx->inputs_ptr()->at(0)->sequence(); + ////const auto& in = tx->inputs_ptr()->at(0)->script(); + ////const auto& out = tx->inputs_ptr()->at(0)->prevout->script(); + ////const auto connect = tx->connect(state); + + ////logger(format("tx_hash [%1%]") % encode_hash(tx_hash)); + ////logger(format("tx_link [%1%]") % tx_link.value); + ////logger(format("result [%1%]") % to_int(result)); + ////logger(format("size [%1%]") % size); + ////logger(format("weight [%1%]") % weight); + ////logger(format("version [%1%]") % version); + ////logger(format("locktime [%1%]") % locktime); + ////logger(format("fee [%1%]") % fee); + ////logger(format("sequence [%1%]") % sequence); + ////logger(format("in [%1%]") % in.to_string(chain::flags::no_rules)); + ////logger(format("out [%1%]") % out.to_string(chain::flags::no_rules)); + ////logger(format("connect [%1%]") % connect.message()); } #endif // UNDEFINED diff --git a/include/bitcoin/node/error.hpp b/include/bitcoin/node/error.hpp index a24afedc6..cce33949c 100644 --- a/include/bitcoin/node/error.hpp +++ b/include/bitcoin/node/error.hpp @@ -83,6 +83,8 @@ enum error_t : uint8_t validate5, validate6, validate7, + validate8, + validate9, confirm1, confirm2, confirm3, diff --git a/src/chasers/chaser_confirm.cpp b/src/chasers/chaser_confirm.cpp index cd69296b3..497fc2bc4 100644 --- a/src/chasers/chaser_confirm.cpp +++ b/src/chasers/chaser_confirm.cpp @@ -156,10 +156,14 @@ void chaser_confirm::do_regressed(height_t branch_point) NOEXCEPT for (auto height = position(); height > branch_point; --height) { - if (!query.set_unstrong(query.to_candidate(height))) + const auto link = query.to_candidate(height); + if (!query.set_unstrong(link)) { - fault(error::confirm1); - return; + if (query.get_block_state(link) != database::error::unassociated) + { + fault(error::confirm1); + return; + } } } @@ -215,22 +219,23 @@ void chaser_confirm::do_bump(height_t) NOEXCEPT // Confirmation query. if ((ec = query.block_confirmable(link))) { - if (ec == database::error::integrity) + if (database::error::error_category::contains(ec)) { - fault(error::confirm2); + LOGR("Confirm fault [" << height << "] " << ec.message()); + fault(ec); return; } // Unset from set before if not using prevout table. if (!prevout_ && !query.set_unstrong(link)) { - fault(error::confirm5); + fault(error::confirm3); return; } if (!query.set_block_unconfirmable(link)) { - fault(error::confirm3); + fault(error::confirm4); return; } @@ -242,14 +247,14 @@ void chaser_confirm::do_bump(height_t) NOEXCEPT if (!query.set_block_confirmable(link)) { - fault(error::confirm3); + fault(error::confirm5); return; } // Set after if using prevout table. if (prevout_ && !query.set_strong(link)) { - fault(error::confirm4); + fault(error::confirm6); return; } } @@ -258,32 +263,29 @@ void chaser_confirm::do_bump(height_t) NOEXCEPT // Set in either case. if (!query.set_strong(link)) { - fault(error::confirm5); + fault(error::confirm7); return; } } - else + else if (ec == database::error::block_unconfirmable) + { + return; + } + else //// if (ec == database::error::unknown_state) { - // With or without an error code, shouldn't be here. - // database::error::unassociated [wait state ] - // database::error::unvalidated [wait state ] - // database::error::block_valid [canonical state ] - // database::error::block_confirmable [resurrected state] - // database::error::block_unconfirmable [shouldn't be here] - // database::error::unknown_state [shouldn't be here] - fault(error::confirm6); + fault(error::confirm8); return; } if (!query.set_filter_head(link)) { - fault(error::confirm7); + fault(error::confirm9); return; } ////if (!set_organized(link, height)) ////{ -//// fault(error::confirm8); +//// fault(error::confirm10); //// return; ////} diff --git a/src/chasers/chaser_validate.cpp b/src/chasers/chaser_validate.cpp index 0443cc6a3..94d5bcc55 100644 --- a/src/chasers/chaser_validate.cpp +++ b/src/chasers/chaser_validate.cpp @@ -191,7 +191,7 @@ void chaser_validate::do_bump(height_t) NOEXCEPT if (bypass && !filter_) { - complete_block(error::success, link, height); + complete_block(database::error::success, link, height); } else { @@ -242,8 +242,8 @@ void chaser_validate::validate_block(const header_link& link, POST(tracked_complete_block, ec, link, ctx.height); } -code chaser_validate::populate(bool bypass, const system::chain::block& block, - const system::chain::context& ctx) NOEXCEPT +code chaser_validate::populate(bool bypass, const chain::block& block, + const chain::context& ctx) NOEXCEPT { const auto& query = archive(); @@ -262,12 +262,11 @@ code chaser_validate::populate(bool bypass, const system::chain::block& block, return system::error::missing_previous_output; } - return error::success; + return system::error::success; } -code chaser_validate::validate(bool bypass, const system::chain::block& block, - const database::header_link& link, - const system::chain::context& ctx) NOEXCEPT +code chaser_validate::validate(bool bypass, const chain::block& block, + const database::header_link& link, const chain::context& ctx) NOEXCEPT { code ec{}; if (bypass) @@ -282,10 +281,10 @@ code chaser_validate::validate(bool bypass, const system::chain::block& block, return ec; if (!query.set_prevouts(link, block)) - return error::validate6; + return error::validate8; if (!query.set_block_valid(link, block.fees())) - return error::validate7; + return error::validate9; return ec; } @@ -307,22 +306,16 @@ void chaser_validate::complete_block(const code& ec, const header_link& link, if (ec) { - // Differentiated fault codes for troubleshooting. - if (ec == error::validate1 || - ec == error::validate2 || - ec == error::validate3 || - ec == error::validate4 || - ec == error::validate5 || - ec == error::validate6 || - ec == error::validate7) + if (node::error::error_category::contains(ec)) { + LOGR("Validate fault [" << height << "] " << ec.message()); fault(ec); return; } notify(ec, chase::unvalid, link); fire(events::block_unconfirmable, height); - LOGR("Unconfirmable block [" << height << "] " << ec.message()); + LOGR("Invalid block [" << height << "] " << ec.message()); return; } diff --git a/src/error.cpp b/src/error.cpp index cb61db997..7a986704a 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -73,6 +73,8 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { validate5, "validate5" }, { validate6, "validate6" }, { validate7, "validate7" }, + { validate8, "validate8" }, + { validate9, "validate9" }, { confirm1, "confirm1" }, { confirm2, "confirm2" }, { confirm3, "confirm3" }, diff --git a/src/protocols/protocol_block_in_31800.cpp b/src/protocols/protocol_block_in_31800.cpp index 1d75cfcbd..6ec54fed6 100644 --- a/src/protocols/protocol_block_in_31800.cpp +++ b/src/protocols/protocol_block_in_31800.cpp @@ -281,10 +281,11 @@ bool protocol_block_in_31800::handle_receive_block(const code& ec, // Preconditions. // ........................................................................ - auto& query = archive(); - const chain::block::cptr block{ message->block_ptr }; + // Intentional pointer copy. + const auto block = message->block_ptr; const auto& hash = block->get_hash(); const auto it = map_->find(hash); + auto& query = archive(); if (it == map_->end()) { @@ -322,14 +323,15 @@ bool protocol_block_in_31800::handle_receive_block(const code& ec, return false; } - if (code == system::error::forward_reference) - { - LOGR("Disordered block [" << encode_hash(hash) << ":" << height - << " txs(" << block->transactions() << ")" - << " segregated(" << block->is_segregated() << ")."); - stop(code); - return false; - } + // TODO: why were we not setting this block as unconfirmable? + ////if (code == system::error::forward_reference) + ////{ + //// LOGR("Disordered block [" << encode_hash(hash) << ":" << height + //// << " txs(" << block->transactions() << ")" + //// << " segregated(" << block->is_segregated() << ")."); + //// stop(code); + //// return false; + ////} // Actual block represented by the hash is unconfirmable. if (!query.set_block_unconfirmable(link)) @@ -351,15 +353,8 @@ bool protocol_block_in_31800::handle_receive_block(const code& ec, // Commit block.txs. // ........................................................................ - // IMPORTANT: ~block() releases all memory for parts of itself, as a - // consequence of the custom memory allocator. Therefore, while shared_ptr - // to an element of the block would normally be valid after ~block(), the - // object pointed to will have been deallocated by ~block(). Therefore a - // reference to `block` must be passed to set_code. - // This invokes set_strong when checked. - const auto bytes = block->serialized_size(true); - if (const auto code = query.set_code(*block, link, checked, bytes)) + if (const auto code = query.set_code(*block, link, checked)) { LOGF("Failure storing block [" << encode_hash(hash) << ":" << height << "] from [" << authority() << "] " << code.message()); @@ -377,7 +372,9 @@ bool protocol_block_in_31800::handle_receive_block(const code& ec, notify(ec, chase::checked, height); fire(events::block_archived, height); - count(bytes); + // block->serialized_size may keep block in scope during set_code above. + // However the compiler may reorder this calculation since block is const. + count(block->serialized_size(true)); map_->erase(it); if (is_idle()) {