aa69d8596f63efd15c09011fc50c5af8795c74a2
[rust-lightning] / lightning / src / chain / chaininterface.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! Traits and utility impls which allow other parts of rust-lightning to interact with the
11 //! blockchain.
12 //!
13 //! Includes traits for monitoring and receiving notifications of new blocks and block
14 //! disconnections, transaction broadcasting, and feerate information requests.
15
16 use bitcoin::blockdata::block::{Block, BlockHeader};
17 use bitcoin::blockdata::transaction::Transaction;
18 use bitcoin::blockdata::script::Script;
19 use bitcoin::hash_types::Txid;
20
21 use std::sync::{Mutex, Arc};
22 use std::collections::HashSet;
23 use std::ops::Deref;
24 use std::marker::PhantomData;
25 use std::ptr;
26
27 /// An interface to send a transaction to the Bitcoin network.
28 pub trait BroadcasterInterface: Sync + Send {
29         /// Sends a transaction out to (hopefully) be mined.
30         fn broadcast_transaction(&self, tx: &Transaction);
31 }
32
33 /// A trait indicating a desire to listen for events from the chain
34 pub trait ChainListener: Sync + Send {
35         /// Notifies a listener that a block was connected. Transactions may be filtered and are given
36         /// paired with their position within the block.
37         fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32);
38
39         /// Notifies a listener that a block was disconnected.
40         /// Unlike block_connected, this *must* never be called twice for the same disconnect event.
41         /// Height must be the one of the block which was disconnected (not new height of the best chain)
42         fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32);
43 }
44
45 /// An enum that represents the speed at which we want a transaction to confirm used for feerate
46 /// estimation.
47 pub enum ConfirmationTarget {
48         /// We are happy with this transaction confirming slowly when feerate drops some.
49         Background,
50         /// We'd like this transaction to confirm without major delay, but 12-18 blocks is fine.
51         Normal,
52         /// We'd like this transaction to confirm in the next few blocks.
53         HighPriority,
54 }
55
56 /// A trait which should be implemented to provide feerate information on a number of time
57 /// horizons.
58 ///
59 /// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
60 /// called from inside the library in response to ChainListener events, P2P events, or timer
61 /// events).
62 pub trait FeeEstimator: Sync + Send {
63         /// Gets estimated satoshis of fee required per 1000 Weight-Units.
64         ///
65         /// Must be no smaller than 253 (ie 1 satoshi-per-byte rounded up to ensure later round-downs
66         /// don't put us below 1 satoshi-per-byte).
67         ///
68         /// This translates to:
69         ///  * satoshis-per-byte * 250
70         ///  * ceil(satoshis-per-kbyte / 4)
71         fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32;
72 }
73
74 /// Minimum relay fee as required by bitcoin network mempool policy.
75 pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
76
77 /// Utility for tracking registered txn/outpoints and checking for matches
78 #[cfg_attr(test, derive(PartialEq))]
79 pub struct ChainWatchedUtil {
80         watch_all: bool,
81
82         // We are more conservative in matching during testing to ensure everything matches *exactly*,
83         // even though during normal runtime we take more optimized match approaches...
84         #[cfg(test)]
85         watched_txn: HashSet<(Txid, Script)>,
86         #[cfg(not(test))]
87         watched_txn: HashSet<Script>,
88
89         watched_outpoints: HashSet<(Txid, u32)>,
90 }
91
92 impl ChainWatchedUtil {
93         /// Constructs an empty (watches nothing) ChainWatchedUtil
94         pub fn new() -> Self {
95                 Self {
96                         watch_all: false,
97                         watched_txn: HashSet::new(),
98                         watched_outpoints: HashSet::new(),
99                 }
100         }
101
102         /// Registers a tx for monitoring, returning true if it was a new tx and false if we'd already
103         /// been watching for it.
104         pub fn register_tx(&mut self, txid: &Txid, script_pub_key: &Script) -> bool {
105                 if self.watch_all { return false; }
106                 #[cfg(test)]
107                 {
108                         self.watched_txn.insert((txid.clone(), script_pub_key.clone()))
109                 }
110                 #[cfg(not(test))]
111                 {
112                         let _tx_unused = txid; // It's used in cfg(test), though
113                         self.watched_txn.insert(script_pub_key.clone())
114                 }
115         }
116
117         /// Registers an outpoint for monitoring, returning true if it was a new outpoint and false if
118         /// we'd already been watching for it
119         pub fn register_outpoint(&mut self, outpoint: (Txid, u32), _script_pub_key: &Script) -> bool {
120                 if self.watch_all { return false; }
121                 self.watched_outpoints.insert(outpoint)
122         }
123
124         /// Sets us to match all transactions, returning true if this is a new setting and false if
125         /// we'd already been set to match everything.
126         pub fn watch_all(&mut self) -> bool {
127                 if self.watch_all { return false; }
128                 self.watch_all = true;
129                 true
130         }
131
132         /// Checks if a given transaction matches the current filter.
133         pub fn does_match_tx(&self, tx: &Transaction) -> bool {
134                 if self.watch_all {
135                         return true;
136                 }
137                 for out in tx.output.iter() {
138                         #[cfg(test)]
139                         for &(ref txid, ref script) in self.watched_txn.iter() {
140                                 if *script == out.script_pubkey {
141                                         if tx.txid() == *txid {
142                                                 return true;
143                                         }
144                                 }
145                         }
146                         #[cfg(not(test))]
147                         for script in self.watched_txn.iter() {
148                                 if *script == out.script_pubkey {
149                                         return true;
150                                 }
151                         }
152                 }
153                 for input in tx.input.iter() {
154                         for outpoint in self.watched_outpoints.iter() {
155                                 let &(outpoint_hash, outpoint_index) = outpoint;
156                                 if outpoint_hash == input.previous_output.txid && outpoint_index == input.previous_output.vout {
157                                         return true;
158                                 }
159                         }
160                 }
161                 false
162         }
163 }
164
165 /// BlockNotifierArc is useful when you need a BlockNotifier that points to ChainListeners with
166 /// static lifetimes, e.g. when you're using lightning-net-tokio (since tokio::spawn requires
167 /// parameters with static lifetimes). Other times you can afford a reference, which is more
168 /// efficient, in which case BlockNotifierRef is a more appropriate type. Defining these type
169 /// aliases prevents issues such as overly long function definitions.
170 ///
171 /// (C-not exported) as we let clients handle any reference counting they need to do
172 pub type BlockNotifierArc = Arc<BlockNotifier<'static, Arc<ChainListener>>>;
173
174 /// BlockNotifierRef is useful when you want a BlockNotifier that points to ChainListeners
175 /// with nonstatic lifetimes. This is useful for when static lifetimes are not needed. Nonstatic
176 /// lifetimes are more efficient but less flexible, and should be used by default unless static
177 /// lifetimes are required, e.g. when you're using lightning-net-tokio (since tokio::spawn
178 /// requires parameters with static lifetimes), in which case BlockNotifierArc is a more
179 /// appropriate type. Defining these type aliases for common usages prevents issues such as
180 /// overly long function definitions.
181 pub type BlockNotifierRef<'a> = BlockNotifier<'a, &'a ChainListener>;
182
183 /// Utility for notifying listeners when blocks are connected or disconnected.
184 ///
185 /// Rather than using a plain BlockNotifier, it is preferable to use either a BlockNotifierArc
186 /// or a BlockNotifierRef for conciseness. See their documentation for more details, but essentially
187 /// you should default to using a BlockNotifierRef, and use a BlockNotifierArc instead when you
188 /// require ChainListeners with static lifetimes, such as when you're using lightning-net-tokio.
189 pub struct BlockNotifier<'a, CL: Deref + 'a>
190                 where CL::Target: ChainListener + 'a {
191         listeners: Mutex<Vec<CL>>,
192         phantom: PhantomData<&'a ()>,
193 }
194
195 impl<'a, CL: Deref + 'a> BlockNotifier<'a, CL>
196                 where CL::Target: ChainListener + 'a {
197         /// Constructs a new BlockNotifier without any listeners.
198         pub fn new() -> BlockNotifier<'a, CL> {
199                 BlockNotifier {
200                         listeners: Mutex::new(Vec::new()),
201                         phantom: PhantomData,
202                 }
203         }
204
205         /// Register the given listener to receive events.
206         pub fn register_listener(&self, listener: CL) {
207                 let mut vec = self.listeners.lock().unwrap();
208                 vec.push(listener);
209         }
210         /// Unregister the given listener to no longer
211         /// receive events.
212         ///
213         /// If the same listener is registered multiple times, unregistering
214         /// will remove ALL occurrences of that listener. Comparison is done using
215         /// the pointer returned by the Deref trait implementation.
216         ///
217         /// (C-not exported) because the equality check would always fail
218         pub fn unregister_listener(&self, listener: CL) {
219                 let mut vec = self.listeners.lock().unwrap();
220                 // item is a ref to an abstract thing that dereferences to a ChainListener,
221                 // so dereference it twice to get the ChainListener itself
222                 vec.retain(|item | !ptr::eq(&(**item), &(*listener)));
223         }
224
225         /// Notify listeners that a block was connected.
226         pub fn block_connected(&self, block: &Block, height: u32) {
227                 let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
228                 let listeners = self.listeners.lock().unwrap();
229                 for listener in listeners.iter() {
230                         listener.block_connected(&block.header, &txdata, height);
231                 }
232         }
233
234         /// Notify listeners that a block was disconnected.
235         pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
236                 let listeners = self.listeners.lock().unwrap();
237                 for listener in listeners.iter() {
238                         listener.block_disconnected(&header, disconnected_height);
239                 }
240         }
241 }
242
243 #[cfg(test)]
244 mod tests {
245         use bitcoin::blockdata::block::BlockHeader;
246         use bitcoin::blockdata::transaction::Transaction;
247         use super::{BlockNotifier, ChainListener};
248         use std::ptr;
249
250         struct TestChainListener(u8);
251
252         impl ChainListener for TestChainListener {
253                 fn block_connected(&self, _header: &BlockHeader, _txdata: &[(usize, &Transaction)], _height: u32) {}
254                 fn block_disconnected(&self, _header: &BlockHeader, _disconnected_height: u32) {}
255         }
256
257         #[test]
258         fn register_listener_test() {
259                 let block_notifier = BlockNotifier::new();
260                 assert_eq!(block_notifier.listeners.lock().unwrap().len(), 0);
261                 let listener = &TestChainListener(0);
262                 block_notifier.register_listener(listener as &ChainListener);
263                 let vec = block_notifier.listeners.lock().unwrap();
264                 assert_eq!(vec.len(), 1);
265                 let item = vec.first().unwrap();
266                 assert!(ptr::eq(&(**item), listener));
267         }
268
269         #[test]
270         fn unregister_single_listener_test() {
271                 let block_notifier = BlockNotifier::new();
272                 let listener1 = &TestChainListener(1);
273                 let listener2 = &TestChainListener(2);
274                 block_notifier.register_listener(listener1 as &ChainListener);
275                 block_notifier.register_listener(listener2 as &ChainListener);
276                 let vec = block_notifier.listeners.lock().unwrap();
277                 assert_eq!(vec.len(), 2);
278                 drop(vec);
279                 block_notifier.unregister_listener(listener1);
280                 let vec = block_notifier.listeners.lock().unwrap();
281                 assert_eq!(vec.len(), 1);
282                 let item = vec.first().unwrap();
283                 assert!(ptr::eq(&(**item), listener2));
284         }
285
286         #[test]
287         fn unregister_multiple_of_the_same_listeners_test() {
288                 let block_notifier = BlockNotifier::new();
289                 let listener1 = &TestChainListener(1);
290                 let listener2 = &TestChainListener(2);
291                 block_notifier.register_listener(listener1 as &ChainListener);
292                 block_notifier.register_listener(listener1 as &ChainListener);
293                 block_notifier.register_listener(listener2 as &ChainListener);
294                 let vec = block_notifier.listeners.lock().unwrap();
295                 assert_eq!(vec.len(), 3);
296                 drop(vec);
297                 block_notifier.unregister_listener(listener1);
298                 let vec = block_notifier.listeners.lock().unwrap();
299                 assert_eq!(vec.len(), 1);
300                 let item = vec.first().unwrap();
301                 assert!(ptr::eq(&(**item), listener2));
302         }
303 }