use crate::chain::{Chain, SyncState};
use crate::core::core::hash::Hash;
use crate::core::core::hash::Hashed;
use crate::core::core::transaction::Transaction;
use crate::handlers::blocks_api::{BlockHandler, HeaderHandler};
use crate::handlers::chain_api::{ChainHandler, KernelHandler, OutputHandler};
use crate::handlers::pool_api::PoolHandler;
use crate::handlers::transactions_api::TxHashSetHandler;
use crate::handlers::version_api::VersionHandler;
use crate::pool::{self, BlockChain, PoolAdapter, PoolEntry};
use crate::types::{
BlockHeaderPrintable, BlockPrintable, LocatedTxKernel, OutputListing, OutputPrintable, Tip,
Version,
};
use crate::util::RwLock;
use crate::{rest::*, BlockListing};
#[cfg(feature = "libp2p")]
use crate::{Libp2pMessages, Libp2pPeers};
#[cfg(feature = "libp2p")]
use chrono::Utc;
#[cfg(feature = "libp2p")]
use mwc_p2p::libp2p_connection;
use mwc_util::secp::Secp256k1;
use std::sync::Weak;
pub struct Foreign<B, P>
where
B: BlockChain,
P: PoolAdapter,
{
pub peers: Weak<mwc_p2p::Peers>,
pub chain: Weak<Chain>,
pub tx_pool: Weak<RwLock<pool::TransactionPool<B, P>>>,
pub sync_state: Weak<SyncState>,
}
impl<B, P> Foreign<B, P>
where
B: BlockChain,
P: PoolAdapter,
{
pub fn new(
peers: Weak<mwc_p2p::Peers>,
chain: Weak<Chain>,
tx_pool: Weak<RwLock<pool::TransactionPool<B, P>>>,
sync_state: Weak<SyncState>,
) -> Self {
Foreign {
peers,
chain,
tx_pool,
sync_state,
}
}
pub fn get_header(
&self,
height: Option<u64>,
hash: Option<Hash>,
commit: Option<String>,
) -> Result<BlockHeaderPrintable, Error> {
let header_handler = HeaderHandler {
chain: self.chain.clone(),
};
let hash = header_handler.parse_inputs(height, hash, commit)?;
header_handler.get_header_v2(&hash)
}
pub fn get_block(
&self,
height: Option<u64>,
hash: Option<Hash>,
commit: Option<String>,
include_proof: Option<bool>,
include_merkle_proof: Option<bool>,
) -> Result<BlockPrintable, Error> {
let block_handler = BlockHandler {
chain: self.chain.clone(),
};
let hash = block_handler.parse_inputs(height, hash, commit)?;
block_handler.get_block(
&hash,
include_proof.unwrap_or(true),
include_merkle_proof.unwrap_or(false),
)
}
pub fn get_blocks(
&self,
start_height: u64,
end_height: u64,
max: u64,
include_proof: Option<bool>,
) -> Result<BlockListing, Error> {
let block_handler = BlockHandler {
chain: self.chain.clone(),
};
block_handler.get_blocks(start_height, end_height, max, include_proof)
}
pub fn get_version(&self) -> Result<Version, Error> {
let version_handler = VersionHandler {
chain: self.chain.clone(),
};
version_handler.get_version()
}
pub fn get_tip(&self) -> Result<Tip, Error> {
let chain_handler = ChainHandler {
chain: self.chain.clone(),
};
chain_handler.get_tip()
}
pub fn get_kernel(
&self,
excess: String,
min_height: Option<u64>,
max_height: Option<u64>,
) -> Result<LocatedTxKernel, Error> {
let kernel_handler = KernelHandler {
chain: self.chain.clone(),
};
kernel_handler.get_kernel_v2(excess, min_height, max_height)
}
pub fn get_outputs(
&self,
commits: Option<Vec<String>>,
start_height: Option<u64>,
end_height: Option<u64>,
include_proof: Option<bool>,
include_merkle_proof: Option<bool>,
) -> Result<Vec<OutputPrintable>, Error> {
let output_handler = OutputHandler {
chain: self.chain.clone(),
};
output_handler.get_outputs_v2(
commits,
start_height,
end_height,
include_proof,
include_merkle_proof,
)
}
pub fn get_unspent_outputs(
&self,
start_index: u64,
end_index: Option<u64>,
max: u64,
include_proof: Option<bool>,
) -> Result<OutputListing, Error> {
let output_handler = OutputHandler {
chain: self.chain.clone(),
};
output_handler.get_unspent_outputs(start_index, end_index, max, include_proof)
}
pub fn get_pmmr_indices(
&self,
start_block_height: u64,
end_block_height: Option<u64>,
) -> Result<OutputListing, Error> {
let txhashset_handler = TxHashSetHandler {
chain: self.chain.clone(),
};
txhashset_handler.block_height_range_to_pmmr_indices(start_block_height, end_block_height)
}
pub fn get_pool_size(&self) -> Result<usize, Error> {
let pool_handler = PoolHandler {
tx_pool: self.tx_pool.clone(),
};
pool_handler.get_pool_size()
}
pub fn get_stempool_size(&self) -> Result<usize, Error> {
let pool_handler = PoolHandler {
tx_pool: self.tx_pool.clone(),
};
pool_handler.get_stempool_size()
}
pub fn get_unconfirmed_transactions(&self) -> Result<Vec<PoolEntry>, Error> {
let pool_handler = PoolHandler {
tx_pool: self.tx_pool.clone(),
};
pool_handler.get_unconfirmed_transactions()
}
pub fn push_transaction(
&self,
tx: Transaction,
fluff: Option<bool>,
secp: &Secp256k1,
) -> Result<(), Error> {
let tx_hash = tx.hash();
let pool_handler = PoolHandler {
tx_pool: self.tx_pool.clone(),
};
pool_handler.push_transaction(tx, fluff, secp).map_err(|e| {
warn!(
"Unable to push transaction {} into the pool, {}",
tx_hash, e
);
e
})
}
#[cfg(feature = "libp2p")]
pub fn get_libp2p_peers(&self) -> Result<Libp2pPeers, Error> {
let libp2p_peers: Vec<String> = libp2p_connection::get_libp2p_connections()
.iter()
.map(|peer| peer.to_string())
.collect();
let node_peers = if let Some(peers) = self.peers.upgrade() {
let connected_peers: Vec<String> = peers
.iter()
.connected()
.into_iter()
.map(|peer| peer.info.addr.tor_address().unwrap_or("".to_string()))
.filter(|addr| !addr.is_empty())
.collect();
connected_peers
} else {
vec![]
};
Ok(Libp2pPeers {
libp2p_peers,
node_peers,
})
}
#[cfg(feature = "libp2p")]
pub fn get_libp2p_messages(&self) -> Result<Libp2pMessages, Error> {
Ok(Libp2pMessages {
current_time: Utc::now().timestamp(),
libp2p_messages: libp2p_connection::get_received_messages(false)
.iter()
.cloned()
.collect(),
})
}
}