+ let mut block = Self::retrieve_block(client, block_height, logger.clone()).await?;
+ if transaction_index as usize >= block.txdata.len() {
+ log_error!(logger, "Could't find transaction {} in block {}", transaction_index, block_height);
+ return Err(UtxoLookupError::UnknownTx);
+ }
+ let mut transaction = block.txdata.swap_remove(transaction_index as usize);
+ if output_index as usize >= transaction.output.len() {
+ log_error!(logger, "Could't find output {} in transaction {}", output_index, transaction.txid());
+ return Err(UtxoLookupError::UnknownTx);
+ }
+ Ok(transaction.output.swap_remove(output_index as usize))
+ }
+
+ async fn retrieve_block(client: Arc<RestClient>, block_height: u32, logger: L) -> Result<Block, UtxoLookupError> {
+ let uri = format!("blockhashbyheight/{}.bin", block_height);
+ let block_hash_result =
+ client.request_resource::<BinaryResponse, RestBinaryResponse>(&uri).await;
+ let block_hash: Vec<u8> = block_hash_result.map_err(|error| {
+ match error.kind() {
+ ErrorKind::InvalidData => {
+ // the response length was likely 0
+ log_error!(logger, "Could't find block hash at height {}: Invalid response! Please make sure the `-rest=1` flag is set.", block_height);
+ }
+ _ => {
+ log_error!(logger, "Could't find block hash at height {}: {}", block_height, error.to_string());
+ }
+ }
+ UtxoLookupError::UnknownChain
+ })?.0;
+ let block_hash = BlockHash::from_slice(&block_hash).unwrap();
+
+ let block_result = client.get_block(&block_hash).await;
+ match block_result {
+ Ok(BlockData::FullBlock(block)) => {
+ Ok(block)
+ },
+ Ok(_) => unreachable!(),
+ Err(error) => {
+ log_error!(logger, "Couldn't retrieve block {}: {:?} ({})", block_height, error, block_hash);
+ Err(UtxoLookupError::UnknownChain)
+ }
+ }
+ }
+}
+
+impl<L: Deref + Clone + Send + Sync + 'static> UtxoLookup for ChainVerifier<L> where L::Target: Logger {
+ fn get_utxo(&self, _genesis_hash: &ChainHash, short_channel_id: u64) -> UtxoResult {
+ let res = UtxoFuture::new();
+ let fut = res.clone();
+ let graph_ref = Arc::clone(&self.graph);
+ let client_ref = Arc::clone(&self.rest_client);
+ let gossip_ref = Arc::clone(&self.outbound_gossiper);
+ let pm_ref = self.peer_handler.lock().unwrap().clone();
+ let logger_ref = self.logger.clone();
+ tokio::spawn(async move {
+ let res = Self::retrieve_utxo(client_ref, short_channel_id, logger_ref).await;
+ fut.resolve(&*graph_ref, &*gossip_ref, res);
+ if let Some(pm) = pm_ref { pm.process_events(); }
+ });
+ UtxoResult::Async(res)