1 //! Traits and utility impls which allow other parts of rust-lightning to interact with the
4 //! Includes traits for monitoring and receiving notifications of new blocks and block
5 //! disconnections, transaction broadcasting, and feerate information requests.
7 use bitcoin::blockdata::block::BlockHeader;
8 use bitcoin::blockdata::transaction::Transaction;
9 use bitcoin::blockdata::script::Script;
10 use bitcoin::hash_types::Txid;
12 use std::collections::HashSet;
14 /// An interface to send a transaction to the Bitcoin network.
15 pub trait BroadcasterInterface: Sync + Send {
16 /// Sends a transaction out to (hopefully) be mined.
17 fn broadcast_transaction(&self, tx: &Transaction);
20 /// A trait indicating a desire to listen for events from the chain
21 pub trait ChainListener: Sync + Send {
22 /// Notifies a listener that a block was connected. Transactions may be filtered and are given
23 /// paired with their position within the block.
24 fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32);
26 /// Notifies a listener that a block was disconnected.
27 /// Unlike block_connected, this *must* never be called twice for the same disconnect event.
28 /// Height must be the one of the block which was disconnected (not new height of the best chain)
29 fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32);
32 /// An enum that represents the speed at which we want a transaction to confirm used for feerate
34 pub enum ConfirmationTarget {
35 /// We are happy with this transaction confirming slowly when feerate drops some.
37 /// We'd like this transaction to confirm without major delay, but 12-18 blocks is fine.
39 /// We'd like this transaction to confirm in the next few blocks.
43 /// A trait which should be implemented to provide feerate information on a number of time
46 /// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
47 /// called from inside the library in response to ChainListener events, P2P events, or timer
49 pub trait FeeEstimator: Sync + Send {
50 /// Gets estimated satoshis of fee required per 1000 Weight-Units.
52 /// Must be no smaller than 253 (ie 1 satoshi-per-byte rounded up to ensure later round-downs
53 /// don't put us below 1 satoshi-per-byte).
55 /// This translates to:
56 /// * satoshis-per-byte * 250
57 /// * ceil(satoshis-per-kbyte / 4)
58 fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32;
61 /// Minimum relay fee as required by bitcoin network mempool policy.
62 pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
64 /// Utility for tracking registered txn/outpoints and checking for matches
65 #[cfg_attr(test, derive(PartialEq))]
66 pub struct ChainWatchedUtil {
69 // We are more conservative in matching during testing to ensure everything matches *exactly*,
70 // even though during normal runtime we take more optimized match approaches...
72 watched_txn: HashSet<(Txid, Script)>,
74 watched_txn: HashSet<Script>,
76 watched_outpoints: HashSet<(Txid, u32)>,
79 impl ChainWatchedUtil {
80 /// Constructs an empty (watches nothing) ChainWatchedUtil
81 pub fn new() -> Self {
84 watched_txn: HashSet::new(),
85 watched_outpoints: HashSet::new(),
89 /// Registers a tx for monitoring, returning true if it was a new tx and false if we'd already
90 /// been watching for it.
91 pub fn register_tx(&mut self, txid: &Txid, script_pub_key: &Script) -> bool {
92 if self.watch_all { return false; }
95 self.watched_txn.insert((txid.clone(), script_pub_key.clone()))
99 let _tx_unused = txid; // It's used in cfg(test), though
100 self.watched_txn.insert(script_pub_key.clone())
104 /// Registers an outpoint for monitoring, returning true if it was a new outpoint and false if
105 /// we'd already been watching for it
106 pub fn register_outpoint(&mut self, outpoint: (Txid, u32), _script_pub_key: &Script) -> bool {
107 if self.watch_all { return false; }
108 self.watched_outpoints.insert(outpoint)
111 /// Sets us to match all transactions, returning true if this is a new setting and false if
112 /// we'd already been set to match everything.
113 pub fn watch_all(&mut self) -> bool {
114 if self.watch_all { return false; }
115 self.watch_all = true;
119 /// Checks if a given transaction matches the current filter.
120 pub fn does_match_tx(&self, tx: &Transaction) -> bool {
124 for out in tx.output.iter() {
126 for &(ref txid, ref script) in self.watched_txn.iter() {
127 if *script == out.script_pubkey {
128 if tx.txid() == *txid {
134 for script in self.watched_txn.iter() {
135 if *script == out.script_pubkey {
140 for input in tx.input.iter() {
141 for outpoint in self.watched_outpoints.iter() {
142 let &(outpoint_hash, outpoint_index) = outpoint;
143 if outpoint_hash == input.previous_output.txid && outpoint_index == input.previous_output.vout {