X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fverifier.rs;h=c44cb663158e19d7e1c850b22bd57f6f952665c1;hb=81c27c87b10f2e097eef99e0766d1bcef2ebef60;hp=4bda871ad124d85336576f0b2e9b08e3b9c5a92b;hpb=4d776e5e9e51758f17dee01a7b8e186f1091e460;p=rapid-gossip-sync-server diff --git a/src/verifier.rs b/src/verifier.rs index 4bda871..c44cb66 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -1,60 +1,79 @@ -use std::convert::TryInto; +use std::io::ErrorKind; +use std::ops::Deref; use std::sync::Arc; use std::sync::Mutex; +use bitcoin::blockdata::constants::ChainHash; use bitcoin::{BlockHash, TxOut}; use bitcoin::blockdata::block::Block; use bitcoin::hashes::Hash; +use lightning::log_error; use lightning::routing::gossip::{NetworkGraph, P2PGossipSync}; use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoResult, UtxoLookupError}; +use lightning::util::logger::Logger; use lightning_block_sync::{BlockData, BlockSource}; use lightning_block_sync::http::BinaryResponse; use lightning_block_sync::rest::RestClient; use crate::config; -use crate::TestLogger; use crate::types::GossipPeerManager; -pub(crate) struct ChainVerifier { +pub(crate) struct ChainVerifier where L::Target: Logger { rest_client: Arc, - graph: Arc>, - outbound_gossiper: Arc>, Arc, TestLogger>>, - peer_handler: Mutex>, + graph: Arc>, + outbound_gossiper: Arc>, Arc, L>>, + peer_handler: Mutex>>, + logger: L } struct RestBinaryResponse(Vec); -impl ChainVerifier { - pub(crate) fn new(graph: Arc>, outbound_gossiper: Arc>, Arc, TestLogger>>) -> Self { +impl ChainVerifier where L::Target: Logger { + pub(crate) fn new(graph: Arc>, outbound_gossiper: Arc>, Arc, L>>, logger: L) -> Self { ChainVerifier { rest_client: Arc::new(RestClient::new(config::bitcoin_rest_endpoint()).unwrap()), outbound_gossiper, graph, peer_handler: Mutex::new(None), + logger } } - pub(crate) fn set_ph(&self, peer_handler: GossipPeerManager) { + pub(crate) fn set_ph(&self, peer_handler: GossipPeerManager) { *self.peer_handler.lock().unwrap() = Some(peer_handler); } - async fn retrieve_utxo(client: Arc, short_channel_id: u64) -> Result { + async fn retrieve_utxo(client: Arc, short_channel_id: u64, logger: L) -> Result { let block_height = (short_channel_id >> 5 * 8) as u32; // block height is most significant three bytes let transaction_index = ((short_channel_id >> 2 * 8) & 0xffffff) as u32; let output_index = (short_channel_id & 0xffff) as u16; - let mut block = Self::retrieve_block(client, block_height).await?; - if transaction_index as usize >= block.txdata.len() { return Err(UtxoLookupError::UnknownTx); } + 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() { return Err(UtxoLookupError::UnknownTx); } + 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, block_height: u32) -> Result { + async fn retrieve_block(client: Arc, block_height: u32, logger: L) -> Result { let uri = format!("blockhashbyheight/{}.bin", block_height); let block_hash_result = client.request_resource::(&uri).await; let block_hash: Vec = block_hash_result.map_err(|error| { - eprintln!("Could't find block hash at height {}: {}", block_height, error.to_string()); + 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(); @@ -66,23 +85,24 @@ impl ChainVerifier { }, Ok(_) => unreachable!(), Err(error) => { - eprintln!("Couldn't retrieve block {}: {:?} ({})", block_height, error, block_hash); + log_error!(logger, "Couldn't retrieve block {}: {:?} ({})", block_height, error, block_hash); Err(UtxoLookupError::UnknownChain) } } } } -impl UtxoLookup for ChainVerifier { - fn get_utxo(&self, _genesis_hash: &BlockHash, short_channel_id: u64) -> UtxoResult { +impl UtxoLookup for ChainVerifier 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).await; + 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(); } });