use crate::{
blocks::Block,
mempool::reorg_pool::reorg_pool::ReorgPoolConfig,
transactions::{transaction::Transaction, types::Signature},
};
use log::*;
use std::sync::Arc;
use tari_crypto::tari_utilities::hex::Hex;
use ttl_cache::TtlCache;
pub const LOG_TARGET: &str = "c::mp::reorg_pool::reorg_pool_storage";
pub struct ReorgPoolStorage {
config: ReorgPoolConfig,
txs_by_signature: TtlCache<Signature, Arc<Transaction>>,
}
impl ReorgPoolStorage {
pub fn new(config: ReorgPoolConfig) -> Self {
Self {
config,
txs_by_signature: TtlCache::new(config.storage_capacity),
}
}
pub fn insert(&mut self, tx: Arc<Transaction>) {
let tx_key = tx.body.kernels()[0].excess_sig.clone();
trace!(
target: LOG_TARGET,
"Inserting tx into reorg pool: {}",
tx_key.get_signature().to_hex()
);
trace!(target: LOG_TARGET, "Transaction inserted: {}", tx);
let _ = self.txs_by_signature.insert(tx_key, tx, self.config.tx_ttl);
}
pub fn insert_txs(&mut self, txs: Vec<Arc<Transaction>>) {
for tx in txs.into_iter() {
self.insert(tx);
}
}
pub fn has_tx_with_excess_sig(&self, excess_sig: &Signature) -> bool {
self.txs_by_signature.contains_key(excess_sig)
}
fn discard_double_spends(&mut self, published_block: &Block) {
let mut removed_tx_keys: Vec<Signature> = Vec::new();
for (tx_key, ptx) in self.txs_by_signature.iter() {
for input in ptx.body.inputs() {
if published_block.body.inputs().contains(input) {
removed_tx_keys.push(tx_key.clone());
}
}
}
for tx_key in &removed_tx_keys {
trace!(target: LOG_TARGET, "Removed double spends: {:?}", tx_key);
self.txs_by_signature.remove(&tx_key);
}
}
pub fn remove_reorged_txs_and_discard_double_spends(
&mut self,
removed_blocks: Vec<Arc<Block>>,
new_blocks: &[Arc<Block>],
) -> Vec<Arc<Transaction>>
{
for block in new_blocks {
self.discard_double_spends(block);
}
let mut removed_txs: Vec<Arc<Transaction>> = Vec::new();
for block in &removed_blocks {
for kernel in block.body.kernels() {
if let Some(removed_tx) = self.txs_by_signature.remove(&kernel.excess_sig) {
trace!(target: LOG_TARGET, "Removing tx from reorg pool: {:?}", removed_tx);
removed_txs.push(removed_tx);
}
}
}
removed_txs
}
pub fn len(&mut self) -> usize {
self.txs_by_signature.iter().count()
}
pub fn snapshot(&mut self) -> Vec<Arc<Transaction>> {
self.txs_by_signature.iter().map(|(_, tx)| tx).cloned().collect()
}
pub fn calculate_weight(&mut self) -> u64 {
self.txs_by_signature
.iter()
.fold(0, |weight, (_, tx)| weight + tx.calculate_weight())
}
}