@@ -3,4 +3,189 @@ id: blockdata
3
3
title : Blockchain Data
4
4
---
5
5
6
- TODO
6
+ import Tabs from '@theme/Tabs ';
7
+ import TabItem from '@theme/TabItem ';
8
+
9
+ ## Introduction
10
+
11
+ In this guide, we'll explore how to provide chain data to LDK upon startup and
12
+ as new blocks are mined. This allows LDK to maintain channel state and monitor
13
+ for on-chain channel activity.
14
+
15
+ ## Overview
16
+
17
+ LDK maintains channels with your node's peers during the course of node
18
+ operation. When a new channel is opened, the ` ChannelManager ` will keep track of
19
+ the channel's state and tell the ` ChainMonitor ` that a new channel should be
20
+ watched. The ` ChainMonitor ` does so by maintaining a ` ChannelMonitor ` for each
21
+ channel.
22
+
23
+ When a new block is mined, it is connected to the chain while other blocks may
24
+ be disconnected. LDK will process such events as they are fed into it from a
25
+ ` BlockSource ` by:
26
+
27
+ * Updating channel state
28
+ * Signaling back transactions to filter
29
+ * Broadcasting transactions if necessary
30
+
31
+ We will walk through this process as depicted here:
32
+
33
+ ![ LDK block processing] ( assets/ldk-block-processing.svg )
34
+
35
+ ## Block Source
36
+
37
+ Initially, our node doesn't have any channels and hence has no data to monitor
38
+ for on-chain. When a channel is opened with a peer, the ` ChannelManager ` creates
39
+ a ` ChannelMonitor ` and passes it to the ` ChainMonitor ` to watch.
40
+
41
+ At this point, LDK needs to be fed chain data of interest so that it can respond
42
+ accordingly. It supports receiving either full blocks or pre-filtered blocks.
43
+ Block data can sourced from anywhere, but it is your responsibility to ensure
44
+ that the necessary ` block_connected ` and ` block_disconnected ` methods are called
45
+ on ` ChannelManager ` and ` ChainMonitor ` . This allows them to update channel state
46
+ and respond to on-chain events, respectively.
47
+
48
+ LDK comes with a ` lightning-block-sync ` utility that handles polling a block
49
+ source for the best chain tip, detecting chain forks, and notifying listeners
50
+ when blocks are connected and disconnected. It can be configured to:
51
+
52
+ * Poll a custom ` BlockSource `
53
+ * Notify ` ChannelManager ` and ` ChainMonitor ` of block events
54
+
55
+ It is your choice as to whether you use this utility or your own to feed the
56
+ required chain data to LDK. If you choose to use it, you will need to implement
57
+ the ` BlockSource ` interface or use one of the samples that it provides.
58
+
59
+ ::: note
60
+ Currently, ` lightning-block-sync ` is only available in Rust.
61
+ :::
62
+
63
+ Implementing the ` BlockSource ` interface requires defining methods for fetching
64
+ headers, blocks, and the best block hash.
65
+
66
+ <Tabs
67
+ defaultValue="rust"
68
+ values={[
69
+ { label: 'Rust', value: 'rust', },
70
+ { label: 'Java', value: 'java', },
71
+ ]
72
+ }>
73
+ <TabItem value =" rust " >
74
+
75
+ ``` rust
76
+ impl BlockSource for Blockchain {
77
+ fn get_header <'a >(& 'a mut self , header_hash : & 'a BlockHash , _height : Option <u32 >) -> AsyncBlockSourceResult <'a , BlockHeaderData > {
78
+ // <insert code for fetching block headers>
79
+ }
80
+
81
+ fn get_block <'a >(& 'a mut self , header_hash : & 'a BlockHash ) -> AsyncBlockSourceResult <'a , Block > {
82
+ // <insert code for fetching block>
83
+ }
84
+
85
+ fn get_best_block <'a >(& 'a mut self ) -> AsyncBlockSourceResult <'a , (BlockHash , Option <u32 >)> {
86
+ // <insert code for fetching the best block hash>
87
+ }
88
+ }
89
+ ```
90
+
91
+ </TabItem >
92
+ <TabItem value =" java " >
93
+
94
+ ``` java
95
+ // TODO
96
+ ```
97
+
98
+ </TabItem >
99
+ </Tabs >
100
+
101
+ For instance, you may implement this interface by querying Bitcoin Core's JSON
102
+ RPC interface, which happens to be a sample implementation provided by
103
+ ` lightning-block-sync ` .
104
+
105
+ Let's walk through the use case where LDK receives full blocks.
106
+
107
+ ### Full Blocks
108
+
109
+ If your Lightning node is backed by a Bitcoin full node, the operation is
110
+ straight forward: call the appropriate methods on ` ChannelManager ` and
111
+ ` ChainMonitor ` as blocks are connected and disconnected. LDK will handle the
112
+ rest!
113
+
114
+ So what happens? The ` ChannelManager ` examines the blocks transactions and
115
+ updates the internal channel state as needed. The ` ChainMonitor ` will detect
116
+ any spends of the channel funding transaction or any pertinent transaction
117
+ outputs, tracking them as necessary.
118
+
119
+ If necessary, LDK will broadcast a transaction on your behalf. More on that
120
+ later. For now, let's look at the more interesting case of pre-filtered blocks.
121
+
122
+ ### Pre-filtered Blocks
123
+
124
+ For environments that are resource constrained, receiving and processing all
125
+ transaction data may not be feasible. LDK handles this case by signaling back
126
+ which transactions and outputs it is interested in. This information can then be
127
+ used to filter blocks prior to sending them to your node.
128
+
129
+ For example, if your block source is an Electrum client, you can pass along this
130
+ information to it. Or if you are making use of a BIP 157 client, you can check
131
+ if a block contains relevant transactions before fetching it.
132
+
133
+ So how does this work in practice? ` ChainMonitor ` is parameterized by an
134
+ optional type that implements ` chain::Filter ` :
135
+
136
+ <Tabs
137
+ defaultValue="rust"
138
+ values={[
139
+ { label: 'Rust', value: 'rust', },
140
+ { label: 'Java', value: 'java', },
141
+ ]
142
+ }>
143
+ <TabItem value =" rust " >
144
+
145
+ ``` rust
146
+ impl chain :: Filter for Blockchain {
147
+ fn register_tx (& self , txid : & Txid , script_pubkey : & Script ) {
148
+ // <insert code for you to watch for this transaction on-chain>
149
+ }
150
+
151
+ fn register_output (& self , outpoint : & OutPoint , script_pubkey : & Script ) {
152
+ // <insert code for you to watch for this output on-chain>
153
+ }
154
+ }
155
+ ```
156
+
157
+ </TabItem >
158
+ <TabItem value =" java " >
159
+
160
+ ``` java
161
+ Filter tx_filter = Filter . new_impl(new Filter .FilterInterface () {
162
+ @Override
163
+ public void register_tx (byte [] txid , byte [] script_pubkey ) {
164
+ // <insert code for you to watch for this transaction on-chain>
165
+ }
166
+
167
+ @Override
168
+ void register_output (OutPoint outpoint , byte [] script_pubkey ) {
169
+ // <insert code for you to watch for this output on-chain>
170
+ }
171
+ });
172
+ ```
173
+
174
+ </TabItem >
175
+ </Tabs >
176
+
177
+ When this is provided, ` ChainMonitor ` will call back to the filter as channels
178
+ are opened and blocks connected. This gives the opportunity for the source to
179
+ pre-filter blocks as desired.
180
+
181
+ Regardless, when a block is connected, its header must be processed by LDK.
182
+
183
+ ## Transaction Broadcast
184
+
185
+ Inevitably, LDK will need to broadcast transactions on your behalf. As you
186
+ notify it of blocks, it will determine if it should broadcast a transaction and
187
+ do so using an implementation of ` BroadcasterInterface ` that you have provided.
188
+
189
+ And as those transactions or those from your peers are confirmed on-chain, they
190
+ will be likewise processed when notified of a connected block. Thus, continuing
191
+ the cycle.
0 commit comments