use std::sync::{Arc, Mutex};
use crate::chaindef::BlockHash;
use crate::chaindef::BlockHeader;
use crate::discovery::announcer::PeerAnnouncer;
use crate::discovery::discoverer::PeerDiscoverer;
use crate::{config::Config, daemon, index, signal::Waiter};
use anyhow::Result;
use bitcoin_hashes::Hash;
pub struct App {
index: index::Index,
daemon: daemon::Daemon,
banner: String,
tip: Mutex<BlockHash>,
discoverer: Arc<PeerDiscoverer>,
announcer: PeerAnnouncer,
}
impl App {
pub fn new(
index: index::Index,
daemon: Arc<daemon::Daemon>,
config: &Config,
discoverer: Arc<PeerDiscoverer>,
announcer: PeerAnnouncer,
) -> Result<Arc<App>> {
Ok(Arc::new(App {
index,
daemon: daemon.reconnect()?,
banner: config.server_banner.clone(),
tip: Mutex::new(BlockHash::all_zeros()),
discoverer,
announcer,
}))
}
pub(crate) fn index(&self) -> &index::Index {
&self.index
}
pub(crate) fn daemon(&self) -> &daemon::Daemon {
&self.daemon
}
pub(crate) fn discoverer(&self) -> &PeerDiscoverer {
&self.discoverer
}
pub(crate) fn announcer(&self) -> &PeerAnnouncer {
&self.announcer
}
pub fn first_update(&self, signal: &Waiter) -> Result<()> {
match self.index.update(signal) {
Ok(_) =>
{
Ok(())
}
Err(e) => Err(e),
}
}
pub fn update(&self, signal: &Waiter) -> Result<(Vec<BlockHeader>, Option<BlockHeader>)> {
let mut tip = self.tip.lock().expect("failed to lock tip");
let new_block = *tip != self.daemon().getbestblockhash()?;
if new_block {
let (new_headers, new_tip) = self.index.update(signal)?;
*tip = new_tip.block_hash();
Ok((new_headers, Some(new_tip)))
} else {
Ok((vec![], None))
}
}
pub fn get_banner(&self) -> Result<String> {
Ok(format!(
"{}\n{}",
self.banner,
self.daemon.get_subversion()?
))
}
}