X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-block-sync%2Fsrc%2Fgossip.rs;fp=lightning-block-sync%2Fsrc%2Fgossip.rs;h=37f4268513f45ec2558a0d8f0635370c37e2d5f0;hb=189c1fbe2c85cad9ae391b2ffe921e30f7d77dbc;hp=4e66c0ce9756f016523bb9a9cfd2d65f973f5eca;hpb=3482fceeab251b2534bf0b7d0ff882db37409d40;p=rust-lightning diff --git a/lightning-block-sync/src/gossip.rs b/lightning-block-sync/src/gossip.rs index 4e66c0ce..37f42685 100644 --- a/lightning-block-sync/src/gossip.rs +++ b/lightning-block-sync/src/gossip.rs @@ -2,7 +2,7 @@ //! current UTXO set. This module defines an implementation of the LDK API required to do so //! against a [`BlockSource`] which implements a few additional methods for accessing the UTXO set. -use crate::{AsyncBlockSourceResult, BlockData, BlockSource}; +use crate::{AsyncBlockSourceResult, BlockData, BlockSource, BlockSourceError}; use bitcoin::blockdata::block::Block; use bitcoin::blockdata::transaction::{TxOut, OutPoint}; @@ -22,6 +22,8 @@ use std::sync::{Arc, Mutex}; use std::collections::VecDeque; use std::future::Future; use std::ops::Deref; +use std::pin::Pin; +use std::task::Poll; /// A trait which extends [`BlockSource`] and can be queried to fetch the block at a given height /// as well as whether a given output is unspent (i.e. a member of the current UTXO set). @@ -62,6 +64,65 @@ impl FutureSpawner for TokioSpawner { } } +/// A trivial future which joins two other futures and polls them at the same time, returning only +/// once both complete. +pub(crate) struct Joiner< + A: Future), BlockSourceError>> + Unpin, + B: Future> + Unpin, +> { + pub a: A, + pub b: B, + a_res: Option<(BlockHash, Option)>, + b_res: Option, +} + +impl< + A: Future), BlockSourceError>> + Unpin, + B: Future> + Unpin, +> Joiner { + fn new(a: A, b: B) -> Self { Self { a, b, a_res: None, b_res: None } } +} + +impl< + A: Future), BlockSourceError>> + Unpin, + B: Future> + Unpin, +> Future for Joiner { + type Output = Result<((BlockHash, Option), BlockHash), BlockSourceError>; + fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll { + if self.a_res.is_none() { + match Pin::new(&mut self.a).poll(ctx) { + Poll::Ready(res) => { + if let Ok(ok) = res { + self.a_res = Some(ok); + } else { + return Poll::Ready(Err(res.unwrap_err())); + } + }, + Poll::Pending => {}, + } + } + if self.b_res.is_none() { + match Pin::new(&mut self.b).poll(ctx) { + Poll::Ready(res) => { + if let Ok(ok) = res { + self.b_res = Some(ok); + } else { + return Poll::Ready(Err(res.unwrap_err())); + } + + }, + Poll::Pending => {}, + } + } + if let Some(b_res) = self.b_res { + if let Some(a_res) = self.a_res { + return Poll::Ready(Ok((a_res, b_res))) + } + } + Poll::Pending + } +} + /// A struct which wraps a [`UtxoSource`] and a few LDK objects and implements the LDK /// [`UtxoLookup`] trait. /// @@ -156,8 +217,20 @@ impl tip_height { + return Err(UtxoLookupError::UnknownTx); + } + } let block_data = source.get_block(&block_hash).await .map_err(|_| UtxoLookupError::UnknownTx)?; let block = match block_data {