Skip to content

Commit ac33af4

Browse files
committed
fixes a clippy lint and a concurrency bug
1 parent 383e62c commit ac33af4

File tree

5 files changed

+65
-40
lines changed

5 files changed

+65
-40
lines changed

zebra-rpc/src/methods/get_block_template_rpcs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,7 @@ where
970970

971971
self.mined_block_sender
972972
.send((block_hash, block_height))
973-
.map_error_with_prefix(0, "failed to send mined block:")?;
973+
.map_error_with_prefix(0, "failed to send mined block")?;
974974

975975
return Ok(submit_block::Response::Accepted);
976976
}

zebra-rpc/src/server/error.rs

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub(crate) trait MapError<T>: Sized {
7070
fn map_error(self, code: impl Into<ErrorCode>) -> std::result::Result<T, ErrorObjectOwned>;
7171

7272
/// Maps errors to [`jsonrpsee_types::ErrorObjectOwned`] with a prefixed message and a specific error code.
73+
#[cfg(feature = "getblocktemplate-rpcs")]
7374
fn map_error_with_prefix(
7475
self,
7576
code: impl Into<ErrorCode>,
@@ -106,6 +107,7 @@ where
106107
self.map_err(|error| ErrorObject::owned(code.into().code(), error.to_string(), None::<()>))
107108
}
108109

110+
#[cfg(feature = "getblocktemplate-rpcs")]
109111
fn map_error_with_prefix(
110112
self,
111113
code: impl Into<ErrorCode>,

zebrad/src/components/inbound/tests/fake_peer_set.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{collections::HashSet, iter, net::SocketAddr, str::FromStr, sync::Arc,
55
use futures::FutureExt;
66
use tokio::{sync::oneshot, task::JoinHandle, time::timeout};
77
use tower::{buffer::Buffer, builder::ServiceBuilder, util::BoxService, Service, ServiceExt};
8-
use tracing::Span;
8+
use tracing::{Instrument, Span};
99

1010
use zebra_chain::{
1111
amount::Amount,
@@ -978,15 +978,18 @@ async fn setup(
978978

979979
#[cfg(feature = "getblocktemplate-rpcs")]
980980
let submitblock_channel = SubmitBlockChannel::new();
981-
let sync_gossip_task_handle = tokio::spawn(sync::gossip_best_tip_block_hashes(
982-
sync_status.clone(),
983-
chain_tip_change.clone(),
984-
peer_set.clone(),
985-
#[cfg(feature = "getblocktemplate-rpcs")]
986-
Some(submitblock_channel.receiver()),
987-
#[cfg(not(feature = "getblocktemplate-rpcs"))]
988-
None,
989-
));
981+
let sync_gossip_task_handle = tokio::spawn(
982+
sync::gossip_best_tip_block_hashes(
983+
sync_status.clone(),
984+
chain_tip_change.clone(),
985+
peer_set.clone(),
986+
#[cfg(feature = "getblocktemplate-rpcs")]
987+
Some(submitblock_channel.receiver()),
988+
#[cfg(not(feature = "getblocktemplate-rpcs"))]
989+
None,
990+
)
991+
.in_current_span(),
992+
);
990993

991994
let tx_gossip_task_handle = tokio::spawn(gossip_mempool_transaction_id(
992995
transaction_receiver,

zebrad/src/components/inbound/tests/real_peer_set.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ async fn setup(
796796
mod submitblock_test {
797797
use std::io;
798798
use std::sync::{Arc, Mutex};
799-
use tracing::Level;
799+
use tracing::{Instrument, Level};
800800
use tracing_subscriber::fmt;
801801

802802
use super::*;
@@ -872,12 +872,15 @@ mod submitblock_test {
872872

873873
// Start the block gossip task with a SubmitBlockChannel
874874
let submitblock_channel = SubmitBlockChannel::new();
875-
let gossip_task_handle = tokio::spawn(sync::gossip_best_tip_block_hashes(
876-
sync_status.clone(),
877-
chain_tip_change,
878-
peer_set.clone(),
879-
Some(submitblock_channel.receiver()),
880-
));
875+
let gossip_task_handle = tokio::spawn(
876+
sync::gossip_best_tip_block_hashes(
877+
sync_status.clone(),
878+
chain_tip_change,
879+
peer_set.clone(),
880+
Some(submitblock_channel.receiver()),
881+
)
882+
.in_current_span(),
883+
);
881884

882885
// Send a block top the channel
883886
submitblock_channel

zebrad/src/components/sync/gossip.rs

+39-22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use futures::TryFutureExt;
66
use thiserror::Error;
77
use tokio::sync::watch;
88
use tower::{timeout::Timeout, Service, ServiceExt};
9+
use tracing::Instrument;
910

1011
use zebra_chain::block;
1112
use zebra_network as zn;
@@ -45,7 +46,7 @@ pub enum BlockGossipError {
4546
///
4647
/// [`block::Hash`]: zebra_chain::block::Hash
4748
pub async fn gossip_best_tip_block_hashes<ZN>(
48-
mut sync_status: SyncStatus,
49+
sync_status: SyncStatus,
4950
mut chain_state: ChainTipChange,
5051
broadcast_network: ZN,
5152
mut mined_block_receiver: Option<watch::Receiver<(block::Hash, block::Height)>>,
@@ -61,40 +62,56 @@ where
6162
let mut broadcast_network = Timeout::new(broadcast_network, TIPS_RESPONSE_TIMEOUT);
6263

6364
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+
{
7193
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?
7797
},
7898

79-
recv_result = mined_block_receiver.changed() => {
80-
recv_result.map_err(SyncStatus)?;
99+
Ok(_) = mined_block_receiver.changed() => {
81100
// 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)
83102
}
84103
}
85104
} 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?
91106
};
92107

108+
chain_state = updated_chain_state;
109+
93110
// block broadcasts inform other nodes about new blocks,
94111
// so our internal Grow or Reset state doesn't matter to them
95112
let request = zn::Request::AdvertiseBlock(hash);
96113

97-
debug!(?height, ?request, "sending committed block broadcast");
114+
info!(?height, ?request, log_msg);
98115
// broadcast requests don't return errors, and we'd just want to ignore them anyway
99116
let _ = broadcast_network
100117
.ready()

0 commit comments

Comments
 (0)