When a we're in normal (in-sync) mode and we get a block that doesn't link to the chain, restart sync with that peer to try to get the missing block

This commit is contained in:
Eric Frias 2015-09-21 16:15:51 -04:00
parent 9536350a50
commit 5bfbe0df86
2 changed files with 26 additions and 10 deletions

View file

@ -411,6 +411,10 @@ namespace detail {
} }
return result; return result;
} catch ( const graphene::chain::unlinkable_block_exception& e ) {
// translate to a graphene::net exception
elog("Error when pushing block:\n${e}", ("e", e.to_detail_string()));
FC_THROW_EXCEPTION(graphene::net::unlinkable_block_exception, "Error when pushing block:\n${e}", ("e", e.to_detail_string()));
} catch( const fc::exception& e ) { } catch( const fc::exception& e ) {
elog("Error when pushing block:\n${e}", ("e", e.to_detail_string())); elog("Error when pushing block:\n${e}", ("e", e.to_detail_string()));
throw; throw;

View file

@ -3230,10 +3230,10 @@ namespace graphene { namespace net { namespace detail {
fc::time_point message_receive_time = fc::time_point::now(); fc::time_point message_receive_time = fc::time_point::now();
dlog( "received a block from peer ${endpoint}, passing it to client", ("endpoint", originating_peer->get_remote_endpoint() ) ); dlog( "received a block from peer ${endpoint}, passing it to client", ("endpoint", originating_peer->get_remote_endpoint() ) );
std::list<peer_connection_ptr> peers_to_disconnect; std::set<peer_connection_ptr> peers_to_disconnect;
std::string disconnect_reason; std::string disconnect_reason;
fc::oexception disconnect_exception; fc::oexception disconnect_exception;
fc::oexception restart_sync_exception;
try try
{ {
// we can get into an intersting situation near the end of synchronization. We can be in // we can get into an intersting situation near the end of synchronization. We can be in
@ -3250,8 +3250,8 @@ namespace graphene { namespace net { namespace detail {
_delegate->handle_block(block_message_to_process, false, contained_transaction_message_ids); _delegate->handle_block(block_message_to_process, false, contained_transaction_message_ids);
message_validated_time = fc::time_point::now(); message_validated_time = fc::time_point::now();
ilog("Successfully pushed block ${num} (id:${id})", ilog("Successfully pushed block ${num} (id:${id})",
("num", block_message_to_process.block.block_num()) ("num", block_message_to_process.block.block_num())
("id", block_message_to_process.block_id)); ("id", block_message_to_process.block_id));
_most_recent_blocks_accepted.push_back(block_message_to_process.block_id); _most_recent_blocks_accepted.push_back(block_message_to_process.block_id);
bool new_transaction_discovered = false; bool new_transaction_discovered = false;
@ -3313,7 +3313,7 @@ namespace graphene { namespace net { namespace detail {
if (next_fork_block_number != 0 && if (next_fork_block_number != 0 &&
next_fork_block_number <= block_number) next_fork_block_number <= block_number)
{ {
peers_to_disconnect.push_back(peer); peers_to_disconnect.insert(peer);
#ifdef ENABLE_DEBUG_ULOGS #ifdef ENABLE_DEBUG_ULOGS
ulog("Disconnecting from peer because their version is too old. Their version date: ${date}", ("date", peer->graphene_git_revision_unix_timestamp)); ulog("Disconnecting from peer because their version is too old. Their version date: ${date}", ("date", peer->graphene_git_revision_unix_timestamp));
#endif #endif
@ -3334,7 +3334,11 @@ namespace graphene { namespace net { namespace detail {
{ {
throw; throw;
} }
catch ( const fc::exception& e ) catch (const unlinkable_block_exception& e)
{
restart_sync_exception = e;
}
catch (const fc::exception& e)
{ {
// client rejected the block. Disconnect the client and any other clients that offered us this block // client rejected the block. Disconnect the client and any other clients that offered us this block
wlog("Failed to push block ${num} (id:${id}), client rejected block sent by peer", wlog("Failed to push block ${num} (id:${id}), client rejected block sent by peer",
@ -3344,13 +3348,21 @@ namespace graphene { namespace net { namespace detail {
disconnect_exception = e; disconnect_exception = e;
disconnect_reason = "You offered me a block that I have deemed to be invalid"; disconnect_reason = "You offered me a block that I have deemed to be invalid";
peers_to_disconnect.push_back( originating_peer->shared_from_this() ); peers_to_disconnect.insert( originating_peer->shared_from_this() );
/* This loop fails do disconnect the originating peer
for (const peer_connection_ptr& peer : _active_connections) for (const peer_connection_ptr& peer : _active_connections)
if (!peer->ids_of_items_to_get.empty() && peer->ids_of_items_to_get.front() == block_message_to_process.block_id) if (!peer->ids_of_items_to_get.empty() && peer->ids_of_items_to_get.front() == block_message_to_process.block_id)
peers_to_disconnect.push_back(peer); peers_to_disconnect.insert(peer);
*/
} }
if (restart_sync_exception)
{
wlog("Peer ${peer} sent me a block that didn't link to our blockchain. Restarting sync mode with them to get the missing block. "
"Error pushing block was: ${e}",
("peer", originating_peer->get_remote_endpoint())
("e", *restart_sync_exception));
start_synchronizing_with_peer(originating_peer->shared_from_this());
}
for (const peer_connection_ptr& peer : peers_to_disconnect) for (const peer_connection_ptr& peer : peers_to_disconnect)
{ {
wlog("disconnecting client ${endpoint} because it offered us the rejected block", ("endpoint", peer->get_remote_endpoint())); wlog("disconnecting client ${endpoint} because it offered us the rejected block", ("endpoint", peer->get_remote_endpoint()));