From 4d6ef89248457dcc1df302518bddecf5194056f5 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Wed, 27 Jan 2021 14:44:22 -0800 Subject: [PATCH] avoid using async blocks to avoid lifetime bug with generators --- zebrad/src/components/inbound.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/zebrad/src/components/inbound.rs b/zebrad/src/components/inbound.rs index 2ee22474..3f2924b7 100644 --- a/zebrad/src/components/inbound.rs +++ b/zebrad/src/components/inbound.rs @@ -239,24 +239,25 @@ impl Service for Inbound { // // We can't use `call_all` here, because it leaks buffer slots: // https://github.com/tower-rs/tower/blob/master/tower/src/util/call_all/common.rs#L112 - let mut state = self.state.clone(); - async move { - let mut blocks = Vec::new(); - for hash in hashes { - let request = zs::Request::Block(hash.into()); - // we can't use ServiceExt::oneshot here, due to lifetime issues - match state.ready_and().await?.call(request).await? { - zs::Response::Block(Some(block)) => blocks.push(block), + use futures::stream::TryStreamExt; + hashes + .into_iter() + .map(|hash| zs::Request::Block(hash.into())) + .map(|request| self.state.clone().oneshot(request)) + .collect::>() + .try_filter_map(|response| async move { + Ok(match response { + zs::Response::Block(Some(block)) => Some(block), // `zcashd` ignores missing blocks in GetData responses, // rather than including them in a trailing `NotFound` // message - zs::Response::Block(None) => {} + zs::Response::Block(None) => None, _ => unreachable!("wrong response from state"), - } - } - Ok(zn::Response::Blocks(blocks)) - } - .boxed() + }) + }) + .try_collect::>() + .map_ok(zn::Response::Blocks) + .boxed() } zn::Request::TransactionsByHash(_transactions) => { // `zcashd` returns a list of found transactions, followed by a