Skip to content

Commit b0ae2af

Browse files
committed
monitoring funding tx mining
1 parent de62c8d commit b0ae2af

File tree

9 files changed

+105
-36
lines changed

9 files changed

+105
-36
lines changed

Cargo.lock

Lines changed: 22 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ bitcoin_scripts = "0.9.0"
5050
bitcoin_blockchain = "0.9.0"
5151
descriptor-wallet = { version = "0.9.0", features = ["keygen", "miniscript", "electrum", "sign", "construct"] }
5252
lnpbp = "0.9.0"
53-
lnp-core = "0.9.1"
53+
lnp-core = "0.9.2"
5454
lnp_rpc = { version = "0.9.1", path = "./rpc" }
5555
internet2 = { version = "0.9.0", features = ["keygen"] }
5656
microservices = { version = "0.9.0", default-features = false, features = ["node", "peer"] }
@@ -84,7 +84,7 @@ amplify = "3.13.0"
8484
lnpbp = "0.9.0"
8585
bitcoin = "0.29.2"
8686
lightning-invoice = "0.21.0"
87-
lnp-core = "0.9.1"
87+
lnp-core = "0.9.2"
8888
lnp_rpc = { version = "0.9.1", path = "./rpc" }
8989
internet2 = "0.9.0"
9090
microservices = { version = "0.9.0", default-features = false, features = ["peer", "shell"] }

cli/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ name = "lnp-cli"
1717

1818
[dependencies]
1919
amplify = "3.13.0"
20-
lnp-core = { version = "0.9.1", default-features = false }
20+
lnp-core = { version = "0.9.2", default-features = false }
2121
lnp_rpc = { version = "0.9.1", path = "../rpc" }
2222
lightning-invoice = { version = "0.21.0", optional = true }
2323
internet2 = "0.9.0"
@@ -32,7 +32,7 @@ clap = { version = "~3.2.23", features = ["derive", "env"] }
3232
clap_complete = "~3.2.5"
3333
lightning-invoice = "0.21.0"
3434
internet2 = "0.9.0"
35-
lnp-core = { version = "0.9.1", default-features = false }
35+
lnp-core = { version = "0.9.2", default-features = false }
3636
lnp_rpc = { version = "0.9.1", path = "../rpc" }
3737
configure_me_codegen = "0.4"
3838

rpc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ name = "lnp_rpc"
1717
amplify = "3.13.0"
1818
strict_encoding = "0.9.0"
1919
bitcoin_scripts = "0.9.0"
20-
lnp-core = { version = "0.9.0", default-features = false }
20+
lnp-core = { version = "0.9.2", default-features = false }
2121
lnpbp = "0.9.0"
2222
bitcoin = { version = "0.29.2", features = ["rand"] }
2323
lightning-invoice = { version = "0.21.0", optional = true }

src/bus/ctl.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub enum CtlMsg {
8686
/// Reports changes in the mining status for previously requested transaction tracked by an
8787
/// on-chain service
8888
#[display("tx_found({0})")]
89-
TxFound(TxStatus),
89+
TxFound(TxConfirmation),
9090

9191
// Routing & payments
9292
/// Request to channel daemon to perform payment using provided route
@@ -260,6 +260,17 @@ pub struct TxStatus {
260260
pub block_pos: Option<BlockPos>,
261261
}
262262

263+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
264+
#[derive(NetworkEncode, NetworkDecode)]
265+
#[display("{txid}, ...")]
266+
pub struct TxConfirmation {
267+
/// Id of a transaction previously requested to be tracked
268+
pub txid: Txid,
269+
270+
/// number of block confirmations
271+
pub confirmations: u32,
272+
}
273+
263274
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, NetworkEncode, NetworkDecode)]
264275
#[display("{client}, {status}")]
265276
pub struct Report {

src/channeld/automata/accept.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,14 @@ fn finish_signed(event: Event<BusMsg>, runtime: &mut Runtime) -> Result<ChannelA
167167
event.endpoints,
168168
LnMsg::FundingSigned(FundingSigned { channel_id, signature: funding.signature }),
169169
)?;
170+
171+
debug!("Waiting for funding transaction {} to be mined", funding.funding_txid);
172+
let core = runtime.state.channel.constructor();
173+
runtime.send_ctl(event.endpoints, ServiceId::Watch, CtlMsg::Track {
174+
txid: funding.funding_txid,
175+
depth: core.common_params().minimum_depth,
176+
})?;
177+
170178
Ok(ChannelAccept::Funded)
171179
}
172180
wrong_msg => {

src/channeld/automata/propose.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,11 @@ fn complete_funding(
284284

285285
let txid = runtime.state.channel.funding().txid();
286286
debug!("Waiting for funding transaction {} to be mined", txid);
287-
runtime.send_ctl(event.endpoints, ServiceId::Watch, CtlMsg::Track { txid, depth: 0 })?;
287+
let core = runtime.state.channel.constructor();
288+
runtime.send_ctl(event.endpoints, ServiceId::Watch, CtlMsg::Track {
289+
txid,
290+
depth: core.common_params().minimum_depth,
291+
})?;
288292

289293
Ok(ChannelPropose::Published)
290294
}

src/watchd/runtime.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn run(config: Config) -> Result<(), Error> {
3434
rx.bind("inproc://electrum-bridge")?;
3535

3636
let (sender, receiver) = mpsc::channel::<ElectrumUpdate>();
37-
let electrum_worker = ElectrumWorker::with(sender, &config.electrum_url, 5)?;
37+
let electrum_worker = ElectrumWorker::with(sender, &config.electrum_url, 15)?;
3838

3939
debug!("Starting electrum watcher thread");
4040
let watcher_runtime = WatcherRuntime::with(receiver, tx)?;
@@ -88,16 +88,14 @@ impl WatcherRuntime {
8888
// TODO: Forward all electrum notifications over the bridge
8989
// self.send_over_bridge(msg.into()).expect("watcher bridge is halted");
9090
match msg {
91-
ElectrumUpdate::TxBatch(transactions, _) => {
91+
ElectrumUpdate::TxConfirmations(transactions, _) => {
9292
for transaction in transactions {
93-
self.send_over_bridge(BusMsg::Ctl(CtlMsg::TxFound(crate::bus::TxStatus {
94-
txid: transaction.txid(),
95-
block_pos: None,
96-
})))
97-
.expect("unable forward electrum notifications over the bridge");
93+
self.send_over_bridge(BusMsg::Ctl(CtlMsg::TxFound(transaction)))
94+
.expect("unable forward electrum notifications over the bridge");
9895
}
9996
}
100-
ElectrumUpdate::Connecting
97+
ElectrumUpdate::TxBatch(..)
98+
| ElectrumUpdate::Connecting
10199
| ElectrumUpdate::Connected
102100
| ElectrumUpdate::Complete
103101
| ElectrumUpdate::FeeEstimate(..)
@@ -170,7 +168,7 @@ impl Runtime {
170168
match request {
171169
CtlMsg::TxFound(tx_status) => {
172170
if let Some((required_height, service_id)) = self.track_list.get(&tx_status.txid) {
173-
if *required_height >= tx_status.block_pos.map(|b| b.pos).unwrap_or_default() {
171+
if *required_height <= tx_status.confirmations {
174172
let service_id = service_id.clone();
175173
self.untrack(tx_status.txid);
176174
match self.electrum_worker.untrack_transaction(tx_status.txid) {

src/watchd/worker.rs

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313

1414
// TODO: Consider making it part of descriptor wallet onchain library
1515

16+
use std::collections::BTreeMap;
1617
use std::sync::mpsc;
1718
use std::thread::{self, JoinHandle};
1819
use std::time::Duration;
1920

20-
use bitcoin::{Transaction, Txid};
21+
use bitcoin::{Script, Transaction, Txid};
2122
use electrum_client::{Client as ElectrumClient, ElectrumApi, HeaderNotification};
2223

24+
use crate::bus::TxConfirmation;
25+
2326
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error, From)]
2427
#[display("failed electrum watcher channel")]
2528
#[from(mpsc::SendError<ElectrumCmd>)]
@@ -48,6 +51,9 @@ pub enum ElectrumUpdate {
4851
#[display("tx_batch(...)")]
4952
TxBatch(Vec<Transaction>, f32),
5053

54+
#[display("tx_confirmations(...)")]
55+
TxConfirmations(Vec<TxConfirmation>, u32),
56+
5157
#[display("channel_disconnected")]
5258
ChannelDisconnected,
5359

@@ -82,7 +88,6 @@ impl ElectrumWorker {
8288
.spawn(move || loop {
8389
thread::sleep(Duration::from_secs(interval));
8490
sender.send(ElectrumCmd::GetTrasactions).expect("Electrum thread is dead");
85-
sender.send(ElectrumCmd::PopHeader).expect("Electrum thread is dead")
8691
})
8792
.expect("unable to start blockchain watcher pacemaker thread");
8893

@@ -190,20 +195,53 @@ impl ElectrumProcessor {
190195
&mut self,
191196
txids: &Vec<Txid>,
192197
) -> Result<Option<ElectrumUpdate>, electrum_client::Error> {
193-
if self.tracks.is_empty() {
198+
if self.tracks.is_empty() || txids.is_empty() {
199+
return Ok(None);
200+
}
201+
let transactions = self.client.batch_transaction_get(txids)?;
202+
let scripts: Vec<Script> =
203+
transactions.into_iter().map(|tx| tx.output[0].script_pubkey.clone()).collect();
204+
205+
let hist = self.client.batch_script_get_history(&scripts)?;
206+
207+
let mut items = vec![];
208+
hist.into_iter().for_each(|mut item| items.append(&mut item));
209+
210+
if items.is_empty() {
194211
return Ok(None);
195212
}
196-
self.client.batch_transaction_get(txids).map(|res| Some(ElectrumUpdate::TxBatch(res, 0.0)))
213+
214+
let transactions: BTreeMap<Txid, i32> =
215+
items.into_iter().map(|h| (h.tx_hash, h.height)).collect();
216+
217+
let min_height = transactions.clone().into_iter().map(|(_, h)| h).min();
218+
let min_height = min_height.unwrap_or_default();
219+
220+
let block_headers = self.client.block_headers(min_height as usize, 50)?;
221+
let block_total = block_headers.headers.len() as i32;
222+
223+
let confirmations: BTreeMap<Txid, i32> = transactions
224+
.into_iter()
225+
.filter(|(_, height)| min_height + block_total > height.to_owned())
226+
.collect();
227+
228+
let confirmations: Vec<TxConfirmation> = confirmations
229+
.into_iter()
230+
.map(|(tx_id, height)| TxConfirmation {
231+
txid: tx_id,
232+
confirmations: (min_height + block_total - height) as u32,
233+
})
234+
.collect();
235+
236+
Ok(Some(ElectrumUpdate::TxConfirmations(confirmations.clone(), confirmations.len() as u32)))
197237
}
198238

199239
fn track_transaction(
200240
&mut self,
201241
txid: Txid,
202242
) -> Result<Option<ElectrumUpdate>, electrum_client::Error> {
203243
self.tracks.push(txid);
204-
self.client
205-
.transaction_get(&txid.clone())
206-
.map(|res| Some(ElectrumUpdate::TxBatch([res].to_vec(), 0.0)))
244+
self.get_transactions(&self.tracks.clone())
207245
}
208246

209247
fn untrack_transaction(
@@ -212,8 +250,6 @@ impl ElectrumProcessor {
212250
) -> Result<Option<ElectrumUpdate>, electrum_client::Error> {
213251
let index = self.tracks.iter().position(|x| *x == txid).unwrap();
214252
self.tracks.remove(index);
215-
self.client
216-
.transaction_get(&txid.clone())
217-
.map(|res| Some(ElectrumUpdate::TxBatch([res].to_vec(), 0.0)))
253+
self.get_transactions(&self.tracks.clone())
218254
}
219255
}

0 commit comments

Comments
 (0)