use blvm_node::config::MempoolPolicyConfig;
use blvm_node::node::mempool::MempoolManager;
use blvm_protocol::{OutPoint, Transaction, TransactionInput, TransactionOutput, UtxoSet, UTXO};
#[tokio::test]
async fn test_mempool_stores_full_transactions() {
let mempool = MempoolManager::new();
let tx = Transaction {
version: 1,
inputs: blvm_protocol::tx_inputs![TransactionInput {
prevout: OutPoint {
hash: [0u8; 32],
index: 0,
},
script_sig: vec![],
sequence: 0xffffffff,
}],
outputs: blvm_protocol::tx_outputs![TransactionOutput {
value: 1000,
script_pubkey: vec![0x51], }],
lock_time: 0,
};
let added = mempool.add_transaction(tx.clone()).unwrap();
assert!(added);
use blvm_protocol::block::calculate_tx_id;
let tx_hash = calculate_tx_id(&tx);
let retrieved = mempool.get_transaction(&tx_hash);
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().version, tx.version);
}
#[tokio::test]
async fn test_mempool_get_prioritized_transactions() {
let mempool = MempoolManager::new();
let mut utxo_set = UtxoSet::default();
let outpoint = OutPoint {
hash: [0u8; 32],
index: 0,
};
utxo_set.insert(
outpoint.clone(),
std::sync::Arc::new(UTXO {
value: 10000,
script_pubkey: vec![0x51].into(),
height: 0,
is_coinbase: false,
}),
);
let high_fee_tx = Transaction {
version: 1,
inputs: blvm_protocol::tx_inputs![TransactionInput {
prevout: outpoint.clone(),
script_sig: vec![],
sequence: 0xffffffff,
}],
outputs: blvm_protocol::tx_outputs![TransactionOutput {
value: 5000, script_pubkey: vec![0x51],
}],
lock_time: 0,
};
let low_fee_tx = Transaction {
version: 1,
inputs: blvm_protocol::tx_inputs![TransactionInput {
prevout: OutPoint {
hash: [1u8; 32],
index: 0,
},
script_sig: vec![],
sequence: 0xffffffff,
}],
outputs: blvm_protocol::tx_outputs![TransactionOutput {
value: 9000, script_pubkey: vec![0x51],
}],
lock_time: 0,
};
mempool.add_transaction(low_fee_tx.clone()).unwrap();
mempool.add_transaction(high_fee_tx.clone()).unwrap();
let prioritized = mempool.get_prioritized_transactions(10, &utxo_set);
assert!(!prioritized.is_empty());
assert_eq!(prioritized[0].version, high_fee_tx.version);
use blvm_protocol::block::calculate_tx_id;
let high_fee_hash = calculate_tx_id(&high_fee_tx);
let prioritized_hashes: Vec<_> = prioritized.iter().map(calculate_tx_id).collect();
assert!(
prioritized_hashes.contains(&high_fee_hash),
"High fee transaction should be in prioritized list"
);
}
#[tokio::test]
async fn test_mempool_remove_transaction() {
let mempool = MempoolManager::new();
let tx = Transaction {
version: 1,
inputs: blvm_protocol::tx_inputs![TransactionInput {
prevout: OutPoint {
hash: [0u8; 32],
index: 0,
},
script_sig: vec![],
sequence: 0xffffffff,
}],
outputs: blvm_protocol::tx_outputs![TransactionOutput {
value: 1000,
script_pubkey: vec![0x51],
}],
lock_time: 0,
};
mempool.add_transaction(tx.clone()).unwrap();
assert_eq!(mempool.size(), 1);
use blvm_protocol::block::calculate_tx_id;
let tx_hash = calculate_tx_id(&tx);
let removed = mempool.remove_transaction(&tx_hash);
assert!(removed);
assert_eq!(mempool.size(), 0);
}
fn dust_spam_tx() -> Transaction {
Transaction {
version: 1,
inputs: blvm_protocol::tx_inputs![TransactionInput {
prevout: OutPoint {
hash: [0u8; 32],
index: 0,
},
script_sig: vec![],
sequence: 0xffffffff,
}],
outputs: blvm_protocol::tx_outputs![TransactionOutput {
value: 100,
script_pubkey: vec![0x51],
}],
lock_time: 0,
}
}
#[tokio::test]
async fn test_reject_spam_in_mempool_rejects_classified_spam() {
let mempool = MempoolManager::new();
let mut policy = MempoolPolicyConfig::default();
policy.reject_spam_in_mempool = true;
mempool.set_policy_config(Some(policy));
let added = mempool.add_transaction(dust_spam_tx()).unwrap();
assert!(
!added,
"expected spam tx rejected when reject_spam_in_mempool is true"
);
assert_eq!(mempool.size(), 0);
}
#[tokio::test]
async fn test_reject_spam_in_mempool_disabled_accepts_same_tx() {
let mempool = MempoolManager::new();
let added = mempool.add_transaction(dust_spam_tx()).unwrap();
assert!(
added,
"default policy should still accept tx classified as spam by heuristics"
);
assert_eq!(mempool.size(), 1);
}