@@ -6,6 +6,7 @@ use futures::TryFutureExt;
6
6
use thiserror:: Error ;
7
7
use tokio:: sync:: watch;
8
8
use tower:: { timeout:: Timeout , Service , ServiceExt } ;
9
+ use tracing:: Instrument ;
9
10
10
11
use zebra_chain:: block;
11
12
use zebra_network as zn;
@@ -45,7 +46,7 @@ pub enum BlockGossipError {
45
46
///
46
47
/// [`block::Hash`]: zebra_chain::block::Hash
47
48
pub async fn gossip_best_tip_block_hashes < ZN > (
48
- mut sync_status : SyncStatus ,
49
+ sync_status : SyncStatus ,
49
50
mut chain_state : ChainTipChange ,
50
51
broadcast_network : ZN ,
51
52
mut mined_block_receiver : Option < watch:: Receiver < ( block:: Hash , block:: Height ) > > ,
@@ -61,40 +62,56 @@ where
61
62
let mut broadcast_network = Timeout :: new ( broadcast_network, TIPS_RESPONSE_TIMEOUT ) ;
62
63
63
64
loop {
64
- // wait for at least one tip change, to make sure we have a new block hash to broadcast
65
- let tip_action = chain_state. wait_for_tip_change ( ) . await . map_err ( TipChange ) ?;
66
- // wait until we're close to the tip, because broadcasts are only useful for nodes near the tip
67
- // (if they're a long way from the tip, they use the syncer and block locators), unless a mined block
68
- // hash is received before `wait_until_close_to_tip()` is ready.
69
- let close_to_tip_fut = sync_status. wait_until_close_to_tip ( ) . map_err ( SyncStatus ) ;
70
- let ( hash, height) = if let Some ( mined_block_receiver) = & mut mined_block_receiver {
65
+ let mut sync_status = sync_status. clone ( ) ;
66
+ let mut chain_tip = chain_state. clone ( ) ;
67
+ let tip_change_close_to_network_tip_fut = async move {
68
+ // wait for at least one tip change, to make sure we have a new block hash to broadcast
69
+ let tip_action = chain_tip. wait_for_tip_change ( ) . await . map_err ( TipChange ) ?;
70
+
71
+ // wait until we're close to the tip, because broadcasts are only useful for nodes near the tip
72
+ // (if they're a long way from the tip, they use the syncer and block locators), unless a mined block
73
+ // hash is received before `wait_until_close_to_tip()` is ready.
74
+ sync_status
75
+ . wait_until_close_to_tip ( )
76
+ . map_err ( SyncStatus )
77
+ . await ?;
78
+
79
+ // get the latest tip change when close to tip - it might be different to the change we awaited,
80
+ // because the syncer might take a long time to reach the tip
81
+ let best_tip = chain_tip
82
+ . last_tip_change ( )
83
+ . unwrap_or ( tip_action)
84
+ . best_tip_hash_and_height ( ) ;
85
+
86
+ Ok ( ( best_tip, "sending committed block broadcast" , chain_tip) )
87
+ }
88
+ . in_current_span ( ) ;
89
+
90
+ let ( ( hash, height) , log_msg, updated_chain_state) = if let Some ( mined_block_receiver) =
91
+ mined_block_receiver. as_mut ( )
92
+ {
71
93
tokio:: select! {
72
- close_to_tip = close_to_tip_fut => {
73
- close_to_tip?;
74
- // get the latest tip change - it might be different to the change we awaited,
75
- // because the syncer might take a long time to reach the tip
76
- chain_state. last_tip_change( ) . unwrap_or( tip_action) . best_tip_hash_and_height( )
94
+ tip_change_close_to_network_tip = tip_change_close_to_network_tip_fut => {
95
+ mined_block_receiver. mark_unchanged( ) ;
96
+ tip_change_close_to_network_tip?
77
97
} ,
78
98
79
- recv_result = mined_block_receiver. changed( ) => {
80
- recv_result. map_err( SyncStatus ) ?;
99
+ Ok ( _) = mined_block_receiver. changed( ) => {
81
100
// we have a new block to broadcast from the `submitblock `RPC method, get block data and release the channel.
82
- * mined_block_receiver. borrow_and_update( )
101
+ ( * mined_block_receiver. borrow_and_update( ) , "sending mined block broadcast" , chain_state )
83
102
}
84
103
}
85
104
} else {
86
- close_to_tip_fut. await ?;
87
- chain_state
88
- . last_tip_change ( )
89
- . unwrap_or ( tip_action)
90
- . best_tip_hash_and_height ( )
105
+ tip_change_close_to_network_tip_fut. await ?
91
106
} ;
92
107
108
+ chain_state = updated_chain_state;
109
+
93
110
// block broadcasts inform other nodes about new blocks,
94
111
// so our internal Grow or Reset state doesn't matter to them
95
112
let request = zn:: Request :: AdvertiseBlock ( hash) ;
96
113
97
- debug ! ( ?height, ?request, "sending committed block broadcast" ) ;
114
+ info ! ( ?height, ?request, log_msg ) ;
98
115
// broadcast requests don't return errors, and we'd just want to ignore them anyway
99
116
let _ = broadcast_network
100
117
. ready ( )
0 commit comments