@@ -609,20 +609,33 @@ namespace eosio {
609
609
610
610
constexpr uint16_t net_version_max = proto_block_nack;
611
611
612
- /* *
613
- * Index by start_block_num
614
- */
615
612
struct peer_sync_state {
616
- explicit peer_sync_state (uint32_t start = 0 , uint32_t end = 0 , uint32_t last_acted = 0 )
617
- :start_block( start ), end_block( end ), last( last_acted ),
618
- start_time(time_point::now())
613
+ enum class sync_t {
614
+ peer_sync, // LIB or head catchup, syncing request_message:catch_up
615
+ block_nack // sync due to block nack (block_notice_message) request_message:normal
616
+ };
617
+ peer_sync_state (uint32_t start, uint32_t end, uint32_t last_acted, sync_t sync_type)
618
+ :start_block( start ), end_block( end ), last( last_acted ), sync_type( sync_type )
619
619
{}
620
+
621
+ bool valid () const ;
622
+
620
623
uint32_t start_block;
621
624
uint32_t end_block;
622
625
uint32_t last; // /< last sent or received
623
- time_point start_time; // /< time request made or received
626
+ sync_t sync_type;
624
627
};
625
628
629
+ bool peer_sync_state::valid () const {
630
+ bool valid = start_block > 0 && end_block >= start_block && last >= start_block-1 && last <= end_block;
631
+ if (sync_type == sync_t ::block_nack && valid) {
632
+ // block nack should only be used for "current" blocks, limit size to something reasonable
633
+ const auto size = end_block - start_block;
634
+ valid = size < 100 ;
635
+ }
636
+ return valid;
637
+ }
638
+
626
639
// thread safe
627
640
class queued_buffer : boost::noncopyable {
628
641
public:
@@ -1011,7 +1024,7 @@ namespace eosio {
1011
1024
1012
1025
void blk_send_branch ( const block_id_type& msg_head_id );
1013
1026
void blk_send_branch_from_nack_request ( const block_id_type& msg_head_id, const block_id_type& req_id );
1014
- void blk_send_branch ( uint32_t msg_head_num, uint32_t fork_db_root_num, uint32_t head_num );
1027
+ void blk_send_branch (uint32_t msg_head_num, uint32_t fork_db_root_num, uint32_t head_num, peer_sync_state:: sync_t sync_type );
1015
1028
1016
1029
void enqueue ( const net_message& msg );
1017
1030
size_t enqueue_block ( const std::vector<char >& sb, uint32_t block_num, queued_buffer::queue_t queue );
@@ -1521,7 +1534,7 @@ namespace eosio {
1521
1534
1522
1535
auto msg_head_num = block_header::num_from_id (msg_head_id);
1523
1536
if (msg_head_num == 0 ) {
1524
- blk_send_branch ( msg_head_num, fork_db_root_num, head_num );
1537
+ blk_send_branch ( msg_head_num, fork_db_root_num, head_num, peer_sync_state:: sync_t ::peer_sync );
1525
1538
return ;
1526
1539
}
1527
1540
@@ -1534,7 +1547,7 @@ namespace eosio {
1534
1547
// if peer on fork, start at their last fork_db_root_num, otherwise we can start at msg_head+1
1535
1548
if (on_fork)
1536
1549
msg_head_num = 0 ;
1537
- blk_send_branch ( msg_head_num, fork_db_root_num, head_num );
1550
+ blk_send_branch ( msg_head_num, fork_db_root_num, head_num, peer_sync_state:: sync_t ::peer_sync );
1538
1551
}
1539
1552
}
1540
1553
@@ -1547,28 +1560,30 @@ namespace eosio {
1547
1560
// a more complicated better approach would be to find where the fork branches and send from there, for now use lib
1548
1561
uint32_t fork_db_root_num = my_impl->get_fork_db_root_num ();
1549
1562
// --fork_db_root_num since blk_send_branch adds one to the request, and we want to start at fork_db_root_num
1550
- blk_send_branch ( --fork_db_root_num, 0 , head_num);
1563
+ blk_send_branch ( --fork_db_root_num, 0 , head_num, peer_sync_state:: sync_t ::block_nack );
1551
1564
} else {
1552
1565
auto msg_req_num = block_header::num_from_id (req_id);
1553
1566
// --msg_req_num since blk_send_branch adds one to the request, and we need to start at msg_req_num
1554
- blk_send_branch ( --msg_req_num, 0 , head_num );
1567
+ blk_send_branch ( --msg_req_num, 0 , head_num, peer_sync_state:: sync_t ::block_nack );
1555
1568
}
1556
1569
}
1557
1570
1558
1571
// called from connection strand
1559
- void connection::blk_send_branch ( uint32_t msg_head_num, uint32_t fork_db_root_num, uint32_t head_num ) {
1572
+ void connection::blk_send_branch ( uint32_t msg_head_num, uint32_t fork_db_root_num, uint32_t head_num, peer_sync_state:: sync_t sync_type ) {
1560
1573
if ( !peer_requested ) {
1561
1574
auto last = msg_head_num != 0 ? msg_head_num : fork_db_root_num;
1562
- peer_requested = peer_sync_state ( last+1 , head_num, last );
1575
+ peer_requested = peer_sync_state ( last+1 , head_num, last, sync_type );
1563
1576
} else {
1564
1577
auto last = msg_head_num != 0 ? msg_head_num : std::min ( peer_requested->last , fork_db_root_num );
1565
1578
uint32_t end = std::max ( peer_requested->end_block , head_num );
1566
1579
if (peer_requested->start_block <= last+1 && peer_requested->end_block >= end)
1567
1580
return ; // nothing to do, send in progress
1568
- peer_requested = peer_sync_state ( last+1 , end, last );
1581
+ peer_requested = peer_sync_state ( last+1 , end, last, sync_type );
1569
1582
}
1570
- if ( peer_requested->start_block <= peer_requested->end_block ) {
1571
- peer_ilog ( this , " enqueue ${s} - ${e}" , (" s" , peer_requested->start_block )(" e" , peer_requested->end_block ) );
1583
+ if ( peer_requested->valid () ) {
1584
+ peer_ilog ( this , " enqueue ${t} ${s} - ${e}" ,
1585
+ (" t" , sync_type == peer_sync_state::sync_t ::peer_sync ? " peer" : " block" )
1586
+ (" s" , peer_requested->start_block )(" e" , peer_requested->end_block ) );
1572
1587
enqueue_sync_block ();
1573
1588
} else {
1574
1589
peer_ilog ( this , " nothing to enqueue" );
@@ -1790,8 +1805,15 @@ namespace eosio {
1790
1805
block_sync_frame_bytes_sent = 0 ;
1791
1806
peer_dlog ( this , " completing enqueue_sync_block ${num}" , (" num" , num) );
1792
1807
}
1808
+ } else if (peer_requested->sync_type == peer_sync_state::sync_t ::block_nack) {
1809
+ // Do not have the block, likely because in the middle of a fork-switch. A fork-switch will send out
1810
+ // block_notice_message for the new blocks. Ignore, similar to the ignore in blk_send_branch().
1811
+ peer_ilog ( this , " enqueue block sync, unable to fetch block ${num}, resetting peer request" , (" num" , num) );
1812
+ peer_requested.reset (); // unable to provide requested blocks
1813
+ block_sync_send_start = 0ns;
1814
+ block_sync_frame_bytes_sent = 0 ;
1793
1815
} else {
1794
- peer_ilog ( this , " enqueue sync, unable to fetch block ${num}, sending benign_other go away" , (" num" , num) );
1816
+ peer_ilog ( this , " enqueue peer sync, unable to fetch block ${num}, sending benign_other go away" , (" num" , num) );
1795
1817
peer_requested.reset (); // unable to provide requested blocks
1796
1818
block_sync_send_start = 0ns;
1797
1819
block_sync_frame_bytes_sent = 0 ;
@@ -2607,10 +2629,12 @@ namespace eosio {
2607
2629
g_cp_conn.unlock ();
2608
2630
if ( fork_db_head_id == null_id ) {
2609
2631
// continue
2610
- } else if ( c && (fork_db_head_num < blk_num || fork_db_head_id == blk_id) ) {
2611
- fc::lock_guard g_conn ( c->conn_mtx );
2612
- c->conn_fork_db_head = null_id;
2613
- c->conn_fork_db_head_num = 0 ;
2632
+ } else if ( fork_db_head_num < blk_num || fork_db_head_id == blk_id ) {
2633
+ if (c) {
2634
+ fc::lock_guard g_conn ( c->conn_mtx );
2635
+ c->conn_fork_db_head = null_id;
2636
+ c->conn_fork_db_head_num = 0 ;
2637
+ }
2614
2638
} else {
2615
2639
set_state_to_head_catchup = true ;
2616
2640
}
@@ -3828,7 +3852,7 @@ namespace eosio {
3828
3852
peer_requested->end_block = std::max (msg.end_block , peer_requested->end_block );
3829
3853
}
3830
3854
else {
3831
- peer_requested = peer_sync_state ( msg.start_block , msg.end_block , msg.start_block -1 );
3855
+ peer_requested = peer_sync_state (msg.start_block , msg.end_block , msg.start_block -1 , peer_sync_state:: sync_t ::peer_sync );
3832
3856
}
3833
3857
enqueue_sync_block ();
3834
3858
}
@@ -4082,19 +4106,19 @@ namespace eosio {
4082
4106
fc_dlog (logger, " on_accepted_block_header ${bn} ${id}" , (" bn" , block->block_num ())(" id" , id));
4083
4107
update_chain_info ();
4084
4108
4085
- boost::asio::post ( my_impl-> thread_pool .get_executor (), [block, id]() {
4109
+ boost::asio::post ( thread_pool.get_executor (), [block, id, this ]() {
4086
4110
fc_dlog (logger, " signaled accepted_block_header, blk num = ${num}, id = ${id}" , (" num" , block->block_num ())(" id" , id));
4087
- my_impl-> dispatcher .bcast_block (block, id);
4111
+ dispatcher.bcast_block (block, id);
4088
4112
});
4089
4113
}
4090
4114
4091
4115
void net_plugin_impl::on_accepted_block ( const signed_block_ptr& block, const block_id_type& id) {
4092
4116
fc_dlog (logger, " on_accepted_block ${bn} ${id}" , (" bn" , block->block_num ())(" id" , id));
4093
4117
update_chain_info ();
4094
4118
4095
- if (my_impl-> chain_plug ->chain ().get_read_mode () != db_read_mode::IRREVERSIBLE) {
4119
+ if (chain_plug->chain ().get_read_mode () != db_read_mode::IRREVERSIBLE) {
4096
4120
// irreversible notifies sync_manager when added to fork_db, non-irreversible notifies when applied
4097
- my_impl-> dispatcher .strand .post ([sync_master = my_impl-> sync_master .get (), block, id]() {
4121
+ dispatcher.strand .post ([sync_master = sync_master.get (), block, id]() {
4098
4122
const fc::microseconds age (fc::time_point::now () - block->timestamp );
4099
4123
sync_master->sync_recv_block (connection_ptr{}, id, block->block_num (), age);
4100
4124
});
@@ -4112,9 +4136,9 @@ namespace eosio {
4112
4136
fc_dlog ( logger, " on_irreversible_block, blk num = ${num}, id = ${id}" , (" num" , block->block_num ())(" id" , id) );
4113
4137
update_chain_info (id);
4114
4138
4115
- if (my_impl-> chain_plug ->chain ().get_read_mode () == db_read_mode::IRREVERSIBLE) {
4139
+ if (chain_plug->chain ().get_read_mode () == db_read_mode::IRREVERSIBLE) {
4116
4140
// irreversible notifies sync_manager when added to fork_db, non-irreversible notifies when applied
4117
- my_impl-> dispatcher .strand .post ([sync_master = my_impl-> sync_master .get (), block, id]() {
4141
+ dispatcher.strand .post ([sync_master = sync_master.get (), block, id]() {
4118
4142
const fc::microseconds age (fc::time_point::now () - block->timestamp );
4119
4143
sync_master->sync_recv_block (connection_ptr{}, id, block->block_num (), age);
4120
4144
});
@@ -4147,7 +4171,7 @@ namespace eosio {
4147
4171
case vote_result_t ::invalid_signature:
4148
4172
case vote_result_t ::max_exceeded: // close peer immediately
4149
4173
fc_elog (vote_logger, " Invalid vote(s), closing connection - ${c}" , (" c" , connection_id));
4150
- my_impl-> connections .any_of_connections ([connection_id](const connection_ptr& c) {
4174
+ connections.any_of_connections ([connection_id](const connection_ptr& c) {
4151
4175
if (c->connection_id == connection_id) {
4152
4176
c->close ( false );
4153
4177
return true ;
@@ -4158,7 +4182,7 @@ namespace eosio {
4158
4182
case vote_result_t ::unknown_block: // track the failure
4159
4183
fc_dlog (vote_logger, " connection - ${c} vote unknown block #${bn}:${id}.." ,
4160
4184
(" c" , connection_id)(" bn" , block_header::num_from_id (msg->block_id ))(" id" , msg->block_id .str ().substr (8 ,16 )));
4161
- my_impl-> connections .any_of_connections ([connection_id](const connection_ptr& c) {
4185
+ connections.any_of_connections ([connection_id](const connection_ptr& c) {
4162
4186
if (c->connection_id == connection_id) {
4163
4187
boost::asio::post (c->strand , [c]() {
4164
4188
c->block_status_monitor_ .rejected ();
@@ -4176,24 +4200,24 @@ namespace eosio {
4176
4200
}
4177
4201
4178
4202
void net_plugin_impl::bcast_vote_message ( uint32_t exclude_peer, const chain::vote_message_ptr& msg ) {
4179
- if (my_impl-> sync_master ->syncing_from_peer ())
4203
+ if (sync_master->syncing_from_peer ())
4180
4204
return ;
4181
4205
4182
4206
fc_dlog (vote_logger, " bcast ${t} vote: block #${bn} ${id}.., ${v}, key ${k}.." ,
4183
4207
(" t" , exclude_peer ? " received" : " our" )(" bn" , block_header::num_from_id (msg->block_id ))(" id" , msg->block_id .str ().substr (8 ,16 ))
4184
4208
(" v" , msg->strong ? " strong" : " weak" )(" k" , msg->finalizer_key .to_string ().substr (8 ,16 )));
4185
4209
4186
- boost::asio::post ( my_impl-> thread_pool .get_executor (), [exclude_peer, msg]() mutable {
4210
+ boost::asio::post ( thread_pool.get_executor (), [exclude_peer, msg, this ]() mutable {
4187
4211
buffer_factory buff_factory;
4188
4212
auto send_buffer = buff_factory.get_send_buffer ( *msg );
4189
4213
4190
- my_impl-> dispatcher .bcast_vote_msg ( exclude_peer, std::move (send_buffer) );
4214
+ dispatcher.bcast_vote_msg ( exclude_peer, std::move (send_buffer) );
4191
4215
});
4192
4216
}
4193
4217
4194
4218
// called from application thread
4195
4219
void net_plugin_impl::transaction_ack (const std::pair<fc::exception_ptr, packed_transaction_ptr>& results) {
4196
- boost::asio::post ( my_impl-> thread_pool .get_executor (), [&dispatcher = my_impl-> dispatcher , results]() {
4220
+ boost::asio::post ( thread_pool.get_executor (), [this , results]() {
4197
4221
const auto & id = results.second ->id ();
4198
4222
if (results.first ) {
4199
4223
fc_dlog ( logger, " signaled NACK, trx-id = ${id} : ${why}" , (" id" , id)( " why" , results.first ->to_detail_string () ) );
0 commit comments