Skip to content

Commit 31bb66d

Browse files
committed
Initial draft of blockchain data guide
1 parent afdcbf3 commit 31bb66d

File tree

2 files changed

+172
-1
lines changed

2 files changed

+172
-1
lines changed

docs/assets/ldk-block-processing.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/blockdata.md

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,174 @@ id: blockdata
33
title: Blockchain Data
44
---
55

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 so has no data to monitor for
38+
on-chain. When a channel is opened with a peer, the `ChannelManager` creates a
39+
`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`.
46+
47+
LDK comes with a `lightning-block-sync` utility that handles polling a block
48+
source for the best chain tip, detecting chain forks, and notifying listeners
49+
when blocks are connected and disconnected. It can be configured to:
50+
51+
* Poll a custom `BlockSource`
52+
* Notify `ChannelManager` and `ChainMonitor` of block events
53+
54+
It is your choice as to whether you use this utility or your own to feed the
55+
required chain data to LDK. If you choose to use it, you will need to implement
56+
the `BlockSource` interface or use one of the samples that it provides.
57+
58+
Implementing the `BlockSource` interface requires defining methods for fetching
59+
headers, blocks, and the best block hash.
60+
61+
<Tabs
62+
defaultValue="rust"
63+
values={[
64+
{ label: 'Rust', value: 'rust', },
65+
{ label: 'Java', value: 'java', },
66+
]
67+
}>
68+
<TabItem value="rust">
69+
70+
```rust
71+
impl BlockSource for Blockchain {
72+
fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, _height: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
73+
//
74+
}
75+
76+
fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
77+
//
78+
}
79+
80+
fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
81+
//
82+
}
83+
}
84+
```
85+
86+
</TabItem>
87+
<TabItem value="java">
88+
89+
```java
90+
// TODO
91+
```
92+
93+
</TabItem>
94+
</Tabs>
95+
96+
For instance, you may implement this interface by querying Bitcoin Core's JSON
97+
RPC interface, which happens to be a sample implementation provided by
98+
`lightning-block-sync`.
99+
100+
Let's walk through the use case where LDK receives full blocks.
101+
102+
### Full Blocks
103+
104+
If your Lightning node is backed by a Bitcoin full node, the operation is
105+
straight forward: call the appropriate methods on `ChannelManager` and
106+
`ChainMonitor` as blocks are connected and disconnected. LDK will handle the
107+
rest!
108+
109+
So what happens? The `ChannelManager` examines the blocks transactions and
110+
updates the internal channel state as needed. The `ChainMonitor` will detect
111+
any spends of the channel funding transaction or any pertinent transaction
112+
outputs of interest, tracking them as necessary.
113+
114+
If necessary, LDK will broadcast a transaction on your behalf. More on that
115+
later. For now, let's look at the more interesting case of pre-filtered blocks.
116+
117+
### Pre-filtered Blocks
118+
119+
For environments that are resource constrained, receiving and processing all
120+
transaction data may not be feasible. LDK handles this case by signaling back
121+
with which transactions and outputs it is interested in. This information can
122+
then be used to filter blocks prior to sending them to your node.
123+
124+
For example, if your block source is an Electrum client, you can pass along this
125+
information to it. Or if you are making use of a BIP 157 client, you can check
126+
if a block contains relevant transactions before fetching it.
127+
128+
Either way, when a block is connected, its header must be processed by LDK.
129+
130+
So how does this work in practice? `ChainMonitor` is parameterized by an
131+
optional type that implements `chain::Filter`:
132+
133+
<Tabs
134+
defaultValue="rust"
135+
values={[
136+
{ label: 'Rust', value: 'rust', },
137+
{ label: 'Java', value: 'java', },
138+
]
139+
}>
140+
<TabItem value="rust">
141+
142+
```rust
143+
impl chain::Filter for Blockchain {
144+
fn register_tx(&self, txid: &Txid, script_pubkey: &Script) {
145+
//
146+
}
147+
148+
fn register_output(&self, outpoint: &OutPoint, script_pubkey: &Script) {
149+
//
150+
}
151+
}
152+
```
153+
154+
</TabItem>
155+
<TabItem value="java">
156+
157+
```java
158+
// TODO
159+
```
160+
161+
</TabItem>
162+
</Tabs>
163+
164+
When this is provided, `ChainMonitor` will call back to the filter as channels
165+
are opened and blocks connected. This gives the opportunity for the source to
166+
pre-filter blocks as desired.
167+
168+
## Transaction Broadcast
169+
170+
Inevitably, LDK will need to broadcast transactions on your behalf. As you
171+
notify it of blocks, it will determine if it should broadcast a transaction and
172+
do so using an implementation of `BroadcasterInterface` that you have provided.
173+
174+
And as those transactions or those from your peers are confirmed on-chain, they
175+
will be likewise processed when notified of a connected block. Thus, continuing
176+
the cycle.

0 commit comments

Comments
 (0)