+ fn get_utxo(&self, genesis_hash: &BlockHash, short_channel_id: u64) -> UtxoResult;
+}
+
+enum ChannelAnnouncement {
+ Full(msgs::ChannelAnnouncement),
+ Unsigned(msgs::UnsignedChannelAnnouncement),
+}
+
+struct UtxoMessages {
+ complete: Option<Result<TxOut, UtxoLookupError>>,
+ channel_announce: Option<ChannelAnnouncement>,
+}
+
+/// Represents a future resolution of a [`UtxoLookup::get_utxo`] query resolving async.
+///
+/// See [`UtxoResult::Async`] and [`UtxoFuture::resolve`] for more info.
+#[derive(Clone)]
+pub struct UtxoFuture {
+ state: Arc<Mutex<UtxoMessages>>,
+}
+
+/// A trivial implementation of [`UtxoLookup`] which is used to call back into the network graph
+/// once we have a concrete resolution of a request.
+struct UtxoResolver(Result<TxOut, UtxoLookupError>);
+impl UtxoLookup for UtxoResolver {
+ fn get_utxo(&self, _genesis_hash: &BlockHash, _short_channel_id: u64) -> UtxoResult {
+ UtxoResult::Sync(self.0.clone())
+ }
+}
+
+impl UtxoFuture {
+ /// Builds a new future for later resolution.
+ pub fn new() -> Self {
+ Self { state: Arc::new(Mutex::new(UtxoMessages {
+ complete: None,
+ channel_announce: None,
+ }))}
+ }
+
+ /// Resolves this future against the given `graph` and with the given `result`.
+ pub fn resolve<L: Deref>(&self, graph: &NetworkGraph<L>, result: Result<TxOut, UtxoLookupError>)
+ where L::Target: Logger {
+ let announcement = {
+ let mut async_messages = self.state.lock().unwrap();
+
+ if async_messages.channel_announce.is_none() {
+ // We raced returning to `check_channel_announcement` which hasn't updated
+ // `channel_announce` yet. That's okay, we can set the `complete` field which it will
+ // check once it gets control again.
+ async_messages.complete = Some(result);
+ return;
+ }
+
+ async_messages.channel_announce.take().unwrap()
+ };
+
+ // Now that we've updated our internal state, pass the pending messages back through the
+ // network graph with a different `UtxoLookup` which will resolve immediately.
+ // Note that we ignore errors as we don't disconnect peers anyway, so there's nothing to do
+ // with them.
+ let resolver = UtxoResolver(result);
+ match announcement {
+ ChannelAnnouncement::Full(signed_msg) => {
+ let _ = graph.update_channel_from_announcement(&signed_msg, &Some(&resolver));
+ },
+ ChannelAnnouncement::Unsigned(msg) => {
+ let _ = graph.update_channel_from_unsigned_announcement(&msg, &Some(&resolver));
+ },
+ }
+ }
+}
+
+/// A set of messages which are pending UTXO lookups for processing.
+pub(super) struct PendingChecks {