rostrum 8.0.0

An efficient implementation of Electrum Server with token support
Documentation
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(_) =>
            /* discard new headers on first update */
            {
                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()?
        ))
    }
}