Implement `ElectrumSyncClient`
[rust-lightning] / lightning-transaction-sync / src / common.rs
1 use lightning::chain::{Confirm, WatchedOutput};
2 use bitcoin::{Txid, BlockHash, Transaction, OutPoint};
3 use bitcoin::block::Header;
4
5 use std::collections::{HashSet, HashMap};
6
7
8 // Represents the current state.
9 pub(crate) struct SyncState {
10         // Transactions that were previously processed, but must not be forgotten
11         // yet since they still need to be monitored for confirmation on-chain.
12         pub watched_transactions: HashSet<Txid>,
13         // Outputs that were previously processed, but must not be forgotten yet as
14         // as we still need to monitor any spends on-chain.
15         pub watched_outputs: HashMap<OutPoint, WatchedOutput>,
16         // The tip hash observed during our last sync.
17         pub last_sync_hash: Option<BlockHash>,
18         // Indicates whether we need to resync, e.g., after encountering an error.
19         pub pending_sync: bool,
20 }
21
22 impl SyncState {
23         pub fn new() -> Self {
24                 Self {
25                         watched_transactions: HashSet::new(),
26                         watched_outputs: HashMap::new(),
27                         last_sync_hash: None,
28                         pending_sync: false,
29                 }
30         }
31         pub fn sync_unconfirmed_transactions(
32                 &mut self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>,
33                 unconfirmed_txs: Vec<Txid>,
34         ) {
35                 for txid in unconfirmed_txs {
36                         for c in confirmables {
37                                 c.transaction_unconfirmed(&txid);
38                         }
39
40                         self.watched_transactions.insert(txid);
41                 }
42         }
43
44         pub fn sync_confirmed_transactions(
45                 &mut self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>,
46                 confirmed_txs: Vec<ConfirmedTx>
47         ) {
48                 for ctx in confirmed_txs {
49                         for c in confirmables {
50                                 c.transactions_confirmed(
51                                         &ctx.block_header,
52                                         &[(ctx.pos, &ctx.tx)],
53                                         ctx.block_height,
54                                 );
55                         }
56
57                         self.watched_transactions.remove(&ctx.tx.txid());
58
59                         for input in &ctx.tx.input {
60                                 self.watched_outputs.remove(&input.previous_output);
61                         }
62                 }
63         }
64 }
65
66
67 // A queue that is to be filled by `Filter` and drained during the next syncing round.
68 pub(crate) struct FilterQueue {
69         // Transactions that were registered via the `Filter` interface and have to be processed.
70         pub transactions: HashSet<Txid>,
71         // Outputs that were registered via the `Filter` interface and have to be processed.
72         pub outputs: HashMap<OutPoint, WatchedOutput>,
73 }
74
75 impl FilterQueue {
76         pub fn new() -> Self {
77                 Self {
78                         transactions: HashSet::new(),
79                         outputs: HashMap::new(),
80                 }
81         }
82
83         // Processes the transaction and output queues and adds them to the given [`SyncState`].
84         //
85         // Returns `true` if new items had been registered.
86         pub fn process_queues(&mut self, sync_state: &mut SyncState) -> bool {
87                 let mut pending_registrations = false;
88
89                 if !self.transactions.is_empty() {
90                         pending_registrations = true;
91
92                         sync_state.watched_transactions.extend(self.transactions.drain());
93                 }
94
95                 if !self.outputs.is_empty() {
96                         pending_registrations = true;
97
98                         sync_state.watched_outputs.extend(self.outputs.drain());
99                 }
100                 pending_registrations
101         }
102 }
103
104 #[derive(Debug)]
105 pub(crate) struct ConfirmedTx {
106         pub tx: Transaction,
107         pub block_header: Header,
108         pub block_height: u32,
109         pub pos: usize,
110 }