Skip to content

Commit 86e4cd9

Browse files
committed
Fix more esplora compilability.
1 parent 194c29e commit 86e4cd9

File tree

3 files changed

+99
-35
lines changed

3 files changed

+99
-35
lines changed

lightning-transaction-sync/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ rustdoc-args = ["--cfg", "docsrs"]
1616
[features]
1717
default = ["time"]
1818
time = []
19-
esplora-async = ["async-interface", "esplora-client/async", "futures"]
20-
esplora-async-https = ["esplora-async", "esplora-client/async-https-rustls"]
19+
esplora-async = ["async-interface", "esplora-client/async", "futures", "electrum-client"]
20+
esplora-async-https = ["esplora-async", "esplora-client/async-https-rustls", "electrum-client"]
2121
esplora-blocking = ["esplora-client/blocking", "electrum-client"]
2222
electrum = ["electrum-client"]
2323
async-interface = []

lightning-transaction-sync/src/electrum.rs

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ use lightning::{log_debug, log_error, log_trace};
1313
use bitcoin::block::Header;
1414
use bitcoin::{BlockHash, Script, Transaction, Txid};
1515

16+
use bitcoin::hashes::Hash as BitcoinHash;
17+
use electrum_client::bitcoin::hashes::Hash as ElectrumHash;
18+
1619
use std::collections::HashSet;
1720
use std::ops::Deref;
1821
use std::sync::Mutex;
1922
use std::time::Instant;
23+
use bitcoin::consensus::{Decodable as BitcoinDecodable, Encodable as BitcoinEncodable};
24+
use electrum_client::bitcoin::consensus::{Decodable as ElectrumDecodable, Encodable as ElectrumEncodable};
2025

2126
/// Synchronizes LDK with a given Electrum server.
2227
///
@@ -97,7 +102,7 @@ where
97102

98103
loop {
99104
let pending_registrations = self.queue.lock().unwrap().process_queues(&mut sync_state);
100-
let tip_is_new = Some(tip_header.block_hash()) != sync_state.last_sync_hash;
105+
let tip_is_new = Some(tip_header.block_hash()) != sync_state.last_sync_hash.map(|h| electrum_client::bitcoin::BlockHash::from_slice(h.as_ref()).unwrap());
101106

102107
// We loop until any registered transactions have been processed at least once, or the
103108
// tip hasn't been updated during the last iteration.
@@ -112,7 +117,14 @@ where
112117
Ok(unconfirmed_txs) => {
113118
// Double-check the tip hash. If it changed, a reorg happened since
114119
// we started syncing and we need to restart last-minute.
115-
match self.check_update_tip(&mut tip_header, &mut tip_height) {
120+
121+
let mut header_buffer = Vec::new();
122+
tip_header.consensus_encode(&mut header_buffer).unwrap();
123+
let mut header_slice = &header_buffer[..];
124+
let header_reader = &mut lightning::util::ser::BufReader::<_, 4096>::new(&mut header_slice);
125+
let mut bitcoin_header = bitcoin::block::Header::consensus_decode(header_reader).unwrap();
126+
127+
match self.check_update_tip(&mut bitcoin_header, &mut tip_height) {
116128
Ok(false) => {
117129
num_unconfirmed += unconfirmed_txs.len();
118130
sync_state.sync_unconfirmed_transactions(
@@ -150,9 +162,15 @@ where
150162
},
151163
}
152164

165+
let mut header_buffer = Vec::new();
166+
tip_header.consensus_encode(&mut header_buffer).unwrap();
167+
let mut header_slice = &header_buffer[..];
168+
let header_reader = &mut lightning::util::ser::BufReader::<_, 4096>::new(&mut header_slice);
169+
let bitcoin_header = bitcoin::block::Header::consensus_decode(header_reader).unwrap();
170+
153171
// Update the best block.
154172
for c in &confirmables {
155-
c.best_block_updated(&tip_header, tip_height);
173+
c.best_block_updated(&bitcoin_header, tip_height);
156174
}
157175

158176
// Prune any sufficiently confirmed output spends
@@ -161,9 +179,16 @@ where
161179

162180
match self.get_confirmed_transactions(&sync_state) {
163181
Ok(confirmed_txs) => {
182+
183+
let mut header_buffer = Vec::new();
184+
tip_header.consensus_encode(&mut header_buffer).unwrap();
185+
let mut header_slice = &header_buffer[..];
186+
let header_reader = &mut lightning::util::ser::BufReader::<_, 4096>::new(&mut header_slice);
187+
let mut bitcoin_header = bitcoin::block::Header::consensus_decode(header_reader).unwrap();
188+
164189
// Double-check the tip hash. If it changed, a reorg happened since
165190
// we started syncing and we need to restart last-minute.
166-
match self.check_update_tip(&mut tip_header, &mut tip_height) {
191+
match self.check_update_tip(&mut bitcoin_header, &mut tip_height) {
167192
Ok(false) => {
168193
num_confirmed += confirmed_txs.len();
169194
sync_state
@@ -207,7 +232,7 @@ where
207232
return Err(TxSyncError::from(err));
208233
},
209234
}
210-
sync_state.last_sync_hash = Some(tip_header.block_hash());
235+
sync_state.last_sync_hash = Some(bitcoin::BlockHash::from_slice(tip_header.block_hash().as_ref()).unwrap());
211236
sync_state.pending_sync = false;
212237
}
213238
}
@@ -240,15 +265,21 @@ where
240265
// Restart if either the tip changed or we got some divergent tip
241266
// change notification since we started. In the latter case we
242267
// make sure we clear the queue before continuing.
243-
let mut restart_sync = check_tip_hash != cur_tip_header.block_hash();
268+
let mut restart_sync = check_tip_hash != electrum_client::bitcoin::BlockHash::from_slice(cur_tip_header.block_hash().as_ref()).unwrap();
244269
while let Some(queued_notif) = self.client.block_headers_pop()? {
245270
if queued_notif.header.block_hash() != check_tip_hash {
246271
restart_sync = true
247272
}
248273
}
249274

250275
if restart_sync {
251-
*cur_tip_header = check_notification.header;
276+
let mut header_buffer = Vec::new();
277+
check_notification.header.consensus_encode(&mut header_buffer).unwrap();
278+
let mut header_slice = &header_buffer[..];
279+
let header_reader = &mut lightning::util::ser::BufReader::<_, 4096>::new(&mut header_slice);
280+
let bitcoin_header = bitcoin::block::Header::consensus_decode(header_reader).unwrap();
281+
282+
*cur_tip_header = bitcoin_header;
252283
*cur_tip_height = check_notification.height as u32;
253284
Ok(true)
254285
} else {
@@ -268,7 +299,7 @@ where
268299
let mut watched_txs = Vec::with_capacity(sync_state.watched_transactions.len());
269300

270301
for txid in &sync_state.watched_transactions {
271-
match self.client.transaction_get(&txid) {
302+
match self.client.transaction_get(&electrum_client::bitcoin::Txid::from_slice(txid.as_ref()).unwrap()) {
272303
Ok(tx) => {
273304
watched_txs.push((txid, tx.clone()));
274305
if let Some(tx_out) = tx.output.first() {
@@ -296,7 +327,7 @@ where
296327
debug_assert_eq!(num_tx_lookups, watched_txs.len());
297328

298329
for output in sync_state.watched_outputs.values() {
299-
watched_script_pubkeys.push(output.script_pubkey.clone());
330+
watched_script_pubkeys.push(electrum_client::bitcoin::ScriptBuf::from_bytes(output.script_pubkey.to_bytes()));
300331
}
301332

302333
let num_output_spend_lookups = watched_script_pubkeys.len() - num_tx_lookups;
@@ -314,10 +345,17 @@ where
314345
continue;
315346
}
316347
let mut filtered_history =
317-
script_history.iter().filter(|h| h.tx_hash == **txid);
348+
script_history.iter().filter(|h| h.tx_hash == electrum_client::bitcoin::Txid::from_slice(txid.as_ref()).unwrap());
318349
if let Some(history) = filtered_history.next() {
350+
351+
let mut tx_buffer = Vec::new();
352+
tx.consensus_encode(&mut tx_buffer).unwrap();
353+
let mut tx_slice = &tx_buffer[..];
354+
let tx_reader = &mut lightning::util::ser::BufReader::<_, 4096>::new(&mut tx_slice);
355+
let bitcoin_transaction = bitcoin::Transaction::consensus_decode(tx_reader).unwrap();
356+
319357
let prob_conf_height = history.height as u32;
320-
let confirmed_tx = self.get_confirmed_tx(tx, prob_conf_height)?;
358+
let confirmed_tx = self.get_confirmed_tx(&bitcoin_transaction, prob_conf_height)?;
321359
confirmed_txs.push(confirmed_tx);
322360
}
323361
debug_assert!(filtered_history.next().is_none());
@@ -332,7 +370,7 @@ where
332370
}
333371

334372
let txid = possible_output_spend.tx_hash;
335-
if confirmed_txs.iter().any(|ctx| ctx.txid == txid) {
373+
if confirmed_txs.iter().any(|ctx| ctx.txid == bitcoin::Txid::from_slice(txid.as_ref()).unwrap()) {
336374
continue;
337375
}
338376

@@ -342,7 +380,13 @@ where
342380
for txin in &tx.input {
343381
let watched_outpoint =
344382
watched_output.outpoint.into_bitcoin_outpoint();
345-
if txin.previous_output == watched_outpoint {
383+
384+
let mut outpoint_buffer = Vec::new();
385+
watched_outpoint.consensus_encode(&mut outpoint_buffer).unwrap();
386+
let mut outpoint_slice = &outpoint_buffer[..];
387+
let esplora_outpoint = electrum_client::bitcoin::OutPoint::consensus_decode(&mut outpoint_slice).unwrap();
388+
389+
if txin.previous_output == esplora_outpoint {
346390
is_spend = true;
347391
break;
348392
}
@@ -353,7 +397,14 @@ where
353397
}
354398

355399
let prob_conf_height = possible_output_spend.height as u32;
356-
let confirmed_tx = self.get_confirmed_tx(&tx, prob_conf_height)?;
400+
401+
let mut tx_buffer = Vec::new();
402+
tx.consensus_encode(&mut tx_buffer).unwrap();
403+
let mut tx_slice = &tx_buffer[..];
404+
let tx_reader = &mut lightning::util::ser::BufReader::<_, 4096>::new(&mut tx_slice);
405+
let bitcoin_transaction = bitcoin::Transaction::consensus_decode(tx_reader).unwrap();
406+
407+
let confirmed_tx = self.get_confirmed_tx(&bitcoin_transaction, prob_conf_height)?;
357408
confirmed_txs.push(confirmed_tx);
358409
},
359410
Err(e) => {
@@ -402,7 +453,7 @@ where
402453
for (txid, conf_height, block_hash_opt) in relevant_txids {
403454
if let Some(block_hash) = block_hash_opt {
404455
let block_header = self.client.block_header(conf_height as usize)?;
405-
if block_header.block_hash() == block_hash {
456+
if block_header.block_hash() == electrum_client::bitcoin::BlockHash::from_slice(block_hash.as_ref()).unwrap() {
406457
// Skip if the tx is still confirmed in the block in question.
407458
continue;
408459
}
@@ -421,24 +472,31 @@ where
421472
&self, tx: &Transaction, prob_conf_height: u32,
422473
) -> Result<ConfirmedTx, InternalError> {
423474
let txid = tx.txid();
424-
match self.client.transaction_get_merkle(&txid, prob_conf_height as usize) {
475+
match self.client.transaction_get_merkle(&electrum_client::bitcoin::Txid::from_slice(txid.as_ref()).unwrap(), prob_conf_height as usize) {
425476
Ok(merkle_res) => {
426477
debug_assert_eq!(prob_conf_height, merkle_res.block_height as u32);
427478
match self.client.block_header(prob_conf_height as usize) {
428479
Ok(block_header) => {
429480
let pos = merkle_res.pos;
430-
if !validate_merkle_proof(&txid, &block_header.merkle_root, &merkle_res) {
481+
if !validate_merkle_proof(&electrum_client::bitcoin::Txid::from_slice(txid.as_ref()).unwrap(), &block_header.merkle_root, &merkle_res) {
431482
log_trace!(
432483
self.logger,
433484
"Inconsistency: Block {} was unconfirmed during syncing.",
434485
block_header.block_hash()
435486
);
436487
return Err(InternalError::Inconsistency);
437488
}
489+
490+
let mut header_buffer = Vec::new();
491+
block_header.consensus_encode(&mut header_buffer).unwrap();
492+
let mut header_slice = &header_buffer[..];
493+
let header_reader = &mut lightning::util::ser::BufReader::<_, 4096>::new(&mut header_slice);
494+
let bitcoin_header = bitcoin::block::Header::consensus_decode(header_reader).unwrap();
495+
438496
let confirmed_tx = ConfirmedTx {
439497
tx: tx.clone(),
440498
txid,
441-
block_header,
499+
block_header: bitcoin_header,
442500
block_height: prob_conf_height,
443501
pos,
444502
};

lightning-transaction-sync/tests/integration_tests.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ use bdk_macros::maybe_await;
1515
use bitcoin::blockdata::block::Header;
1616
use bitcoin::blockdata::constants::genesis_block;
1717
use bitcoin::network::Network;
18-
use bitcoin::{Amount, BlockHash, Txid};
18+
use bitcoin::{BlockHash, Txid};
1919
use bitcoind::bitcoincore_rpc::RpcApi;
2020
use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
2121
use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD};
22+
use bitcoin::hashes::Hash as BitcoinHash;
23+
use electrum_client::bitcoin::hashes::Hash as ElectrumHash;
2224

2325
use std::collections::{HashMap, HashSet};
2426
use std::env;
@@ -183,7 +185,7 @@ macro_rules! test_syncing {
183185
.client
184186
.send_to_address(
185187
&new_address,
186-
Amount::from_sat(5000),
188+
electrum_client::bitcoin::Amount::from_sat(5000),
187189
None,
188190
None,
189191
None,
@@ -196,7 +198,7 @@ macro_rules! test_syncing {
196198
.client
197199
.send_to_address(
198200
&new_address,
199-
Amount::from_sat(5000),
201+
electrum_client::bitcoin::Amount::from_sat(5000),
200202
None,
201203
None,
202204
None,
@@ -205,7 +207,7 @@ macro_rules! test_syncing {
205207
None,
206208
)
207209
.unwrap();
208-
$tx_sync.register_tx(&txid, &new_address.payload().script_pubkey());
210+
$tx_sync.register_tx(&bitcoin::Txid::from_slice(txid.as_ref()).unwrap(), &bitcoin::Script::from_bytes(new_address.payload().script_pubkey().as_ref()));
209211

210212
maybe_await!($tx_sync.sync(vec![&$confirmable])).unwrap();
211213

@@ -219,7 +221,7 @@ macro_rules! test_syncing {
219221

220222
let events = std::mem::take(&mut *$confirmable.events.lock().unwrap());
221223
assert_eq!(events.len(), 2);
222-
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
224+
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&bitcoin::Txid::from_slice(txid.as_ref()).unwrap()));
223225
assert!($confirmable.unconfirmed_txs.lock().unwrap().is_empty());
224226

225227
// Now take an arbitrary output of the second transaction and check we'll confirm its spend.
@@ -235,17 +237,17 @@ macro_rules! test_syncing {
235237
.unwrap();
236238
let prev_script_pubkey = prev_tx.output[prev_outpoint.vout as usize].script_pubkey.clone();
237239
let output = WatchedOutput {
238-
block_hash: Some(block_hash),
239-
outpoint: OutPoint { txid: prev_outpoint.txid, index: prev_outpoint.vout as u16 },
240-
script_pubkey: prev_script_pubkey,
240+
block_hash: Some(bitcoin::BlockHash::from_slice(block_hash.as_ref()).unwrap()),
241+
outpoint: OutPoint { txid: bitcoin::Txid::from_slice(prev_outpoint.txid.as_ref()).unwrap(), index: prev_outpoint.vout as u16 },
242+
script_pubkey: bitcoin::ScriptBuf::from_bytes(prev_script_pubkey.as_bytes().to_vec()),
241243
};
242244

243245
$tx_sync.register_output(output);
244246
maybe_await!($tx_sync.sync(vec![&$confirmable])).unwrap();
245247

246248
let events = std::mem::take(&mut *$confirmable.events.lock().unwrap());
247249
assert_eq!(events.len(), 1);
248-
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
250+
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&bitcoin::Txid::from_slice(second_txid.as_ref()).unwrap()));
249251
assert_eq!($confirmable.confirmed_txs.lock().unwrap().len(), 2);
250252
assert!($confirmable.unconfirmed_txs.lock().unwrap().is_empty());
251253

@@ -266,8 +268,8 @@ macro_rules! test_syncing {
266268
maybe_await!($tx_sync.sync(vec![&$confirmable])).unwrap();
267269

268270
// Transactions still confirmed but under new tip.
269-
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
270-
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
271+
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&bitcoin::Txid::from_slice(txid.as_ref()).unwrap()));
272+
assert!($confirmable.confirmed_txs.lock().unwrap().contains_key(&bitcoin::Txid::from_slice(second_txid.as_ref()).unwrap()));
271273
assert!($confirmable.unconfirmed_txs.lock().unwrap().is_empty());
272274

273275
// Check we got unconfirmed, then reconfirmed in the meantime.
@@ -277,15 +279,17 @@ macro_rules! test_syncing {
277279

278280
match events[0] {
279281
TestConfirmableEvent::Unconfirmed(t) => {
280-
assert!(t == txid || t == second_txid);
282+
let electrum_t = electrum_client::bitcoin::Txid::from_slice(t.as_ref()).unwrap();
283+
assert!(electrum_t == txid || electrum_t == second_txid);
281284
assert!(seen_txids.insert(t));
282285
},
283286
_ => panic!("Unexpected event"),
284287
}
285288

286289
match events[1] {
287290
TestConfirmableEvent::Unconfirmed(t) => {
288-
assert!(t == txid || t == second_txid);
291+
let electrum_t = electrum_client::bitcoin::Txid::from_slice(t.as_ref()).unwrap();
292+
assert!(electrum_t == txid || electrum_t == second_txid);
289293
assert!(seen_txids.insert(t));
290294
},
291295
_ => panic!("Unexpected event"),
@@ -298,15 +302,17 @@ macro_rules! test_syncing {
298302

299303
match events[3] {
300304
TestConfirmableEvent::Confirmed(t, _, _) => {
301-
assert!(t == txid || t == second_txid);
305+
let electrum_t = electrum_client::bitcoin::Txid::from_slice(t.as_ref()).unwrap();
306+
assert!(electrum_t == txid || electrum_t == second_txid);
302307
assert!(seen_txids.remove(&t));
303308
},
304309
_ => panic!("Unexpected event"),
305310
}
306311

307312
match events[4] {
308313
TestConfirmableEvent::Confirmed(t, _, _) => {
309-
assert!(t == txid || t == second_txid);
314+
let electrum_t = electrum_client::bitcoin::Txid::from_slice(t.as_ref()).unwrap();
315+
assert!(electrum_t == txid || electrum_t == second_txid);
310316
assert!(seen_txids.remove(&t));
311317
},
312318
_ => panic!("Unexpected event"),

0 commit comments

Comments
 (0)