// Not having orphans will cause a stall void poller::ask_blocks(const std::error_code& ec, const block_locator_type& locator, const hash_digest& hash_stop, channel_ptr node) { if (!node) return; if (ec) { log_debug(LOG_POLLER) << "Failed to fetch block locator: " << ec.message(); return; } if (is_duplicate_block_ask(locator, hash_stop, node)) { log_debug(LOG_POLLER) << "Skipping duplicate ask blocks with locator front [" << encode_hash(locator.front()) << "]"; return; } log_debug(LOG_POLLER) << "Ask for blocks with stop [" << encode_hash(hash_stop) << "]"; const auto handle_error = [node](const std::error_code& ec) { if (!node) return; if (ec) { log_debug(LOG_POLLER) << "Send get blocks problem: " << ec.message(); // TODO: modify send() to terminate the connection on send failure. node->stop(); } }; // Send get_blocks request. const get_blocks_type packet{ locator, hash_stop }; node->send(packet, handle_error); // Update last values. last_locator_begin_ = locator.front(); last_hash_stop_ = hash_stop; last_requested_node_ = node.get(); }
void poller::handle_store_block(const std::error_code& ec, block_info info, const hash_digest& block_hash, channel_ptr node) { if (ec == error::duplicate) { // This is common, we get blocks we already have. log_debug(LOG_POLLER) << "Redundant block [" << encode_hash(block_hash) << "]"; return; } if (ec) { log_error(LOG_POLLER) << "Error storing block [" << encode_hash(block_hash) << "] " << ec.message(); node->stop(/* ec */); return; } switch (info.status) { // The block has been accepted as an orphan (ec not set). case block_status::orphan: log_debug(LOG_POLLER) << "Potential block [" << encode_hash(block_hash) << "]"; // This is how we get other nodes to send us the blocks we are // missing from the top of our chain to the orphan. request_blocks(block_hash, node); break; // The block has been rejected from the store (redundant?). // This case may be redundant with error::duplicate. case block_status::rejected: log_debug(LOG_POLLER) << "Rejected block [" << encode_hash(block_hash) << "]"; break; // The block has been accepted into the long chain (ec not set). case block_status::confirmed: log_info(LOG_POLLER) << "Block #" << info.height << " " << encode_hash(block_hash); break; } }
void poller::receive_block(const std::error_code& ec, const block_type& block, channel_ptr node) { if (!node) return; if (ec) { log_warning(LOG_POLLER) << "Received bad block: " << ec.message(); node->stop(/* ec */); return; } blockchain_.store(block, strand_.wrap(&poller::handle_store_block, this, _1, _2, hash_block_header(block.header), node)); // Resubscribe. node->subscribe_block( std::bind(&poller::receive_block, this, _1, _2, node)); }
/// Stop the specified channel. void stop(channel_ptr c) { m_channels.erase(c); c->stop(); c.reset(); }