Skip to content

Commit 3726060

Browse files
committed
Include block hash for watched transaction output
When registering a watched transaction output, any in-block descendant transactions spending the output must be supplied. Give the block hash when registering such outputs such that this is possible. Otherwise, spends from other blocks may be returned inadvertently.
1 parent d70fdd3 commit 3726060

File tree

4 files changed

+43
-10
lines changed

4 files changed

+43
-10
lines changed

lightning/src/chain/chainmonitor.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
use bitcoin::blockdata::block::{Block, BlockHeader};
2727

2828
use chain;
29-
use chain::Filter;
29+
use chain::{Filter, WatchedOutput};
3030
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
3131
use chain::channelmonitor;
3232
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist};
@@ -87,9 +87,14 @@ where C::Target: chain::Filter,
8787
let mut txn_outputs = monitor.block_connected(header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
8888

8989
if let Some(ref chain_source) = self.chain_source {
90+
let block_hash = header.block_hash();
9091
for (txid, outputs) in txn_outputs.drain(..) {
9192
for (idx, output) in outputs.iter() {
92-
chain_source.register_output(&OutPoint { txid, index: *idx as u16 }, &output.script_pubkey);
93+
chain_source.register_output(WatchedOutput {
94+
block_hash: Some(block_hash),
95+
outpoint: OutPoint { txid, index: *idx as u16 },
96+
script_pubkey: output.script_pubkey.clone(),
97+
});
9398
}
9499
}
95100
}

lightning/src/chain/channelmonitor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLC
4040
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
4141
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
4242
use chain;
43+
use chain::WatchedOutput;
4344
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
4445
use chain::transaction::{OutPoint, TransactionData};
4546
use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface};
@@ -1174,7 +1175,11 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
11741175
for (txid, outputs) in lock.get_outputs_to_watch().iter() {
11751176
for (index, script_pubkey) in outputs.iter() {
11761177
assert!(*index <= u16::max_value() as u32);
1177-
filter.register_output(&OutPoint { txid: *txid, index: *index as u16 }, script_pubkey);
1178+
filter.register_output(WatchedOutput {
1179+
block_hash: None,
1180+
outpoint: OutPoint { txid: *txid, index: *index as u16 },
1181+
script_pubkey: script_pubkey.clone(),
1182+
});
11781183
}
11791184
}
11801185
}

lightning/src/chain/mod.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,34 @@ pub trait Filter: Send + Sync {
129129
/// a spending condition.
130130
fn register_tx(&self, txid: &Txid, script_pubkey: &Script);
131131

132-
/// Registers interest in spends of a transaction output identified by `outpoint` having
133-
/// `script_pubkey` as the spending condition.
132+
/// Registers interest in spends of a transaction output.
134133
///
135-
/// Optionally, returns any transaction dependent on the output. This is useful for Electrum
136-
/// clients to facilitate registering in-block descendants.
137-
fn register_output(&self, outpoint: &OutPoint, script_pubkey: &Script) -> Option<(usize, Transaction)>;
134+
/// Optionally, when `output.block_hash` is set, should return any transaction spending the
135+
/// output that is found in the corresponding block at the given index.
136+
///
137+
/// This return value is useful for Electrum clients in order to supply in-block descendant
138+
/// transactions which otherwise were not included. This is not necessary for other clients if
139+
/// such descendant transactions were already included (e.g., when a BIP 157 client provides the
140+
/// full block).
141+
fn register_output(&self, output: WatchedOutput) -> Option<(usize, Transaction)>;
142+
}
143+
144+
/// A transaction output watched by a [`ChannelMonitor`] for spends on-chain.
145+
///
146+
/// Used to convey to a [`chain::Filter`] an output identified by `outpoint` having `script_pubkey`
147+
/// as the spending condition. If `block_hash` is `Some`, this indicates the output was spent in the
148+
/// corresponding block.
149+
///
150+
/// [`ChannelMonitor`]: channelmonitor/struct.ChannelMonitor.html
151+
pub struct WatchedOutput {
152+
/// Block where the transaction output may have been spent.
153+
pub block_hash: Option<BlockHash>,
154+
155+
/// Outpoint identifying the transaction output.
156+
pub outpoint: OutPoint,
157+
158+
/// Spending condition of the transaction output.
159+
pub script_pubkey: Script,
138160
}
139161

140162
impl<T: Listen> Listen for std::ops::Deref<Target = T> {

lightning/src/util/test_utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// licenses.
99

1010
use chain;
11+
use chain::WatchedOutput;
1112
use chain::chaininterface;
1213
use chain::chaininterface::ConfirmationTarget;
1314
use chain::chainmonitor;
@@ -546,8 +547,8 @@ impl chain::Filter for TestChainSource {
546547
self.watched_txn.lock().unwrap().insert((*txid, script_pubkey.clone()));
547548
}
548549

549-
fn register_output(&self, outpoint: &OutPoint, script_pubkey: &Script) -> Option<(usize, Transaction)> {
550-
self.watched_outputs.lock().unwrap().insert((*outpoint, script_pubkey.clone()));
550+
fn register_output(&self, output: WatchedOutput) -> Option<(usize, Transaction)> {
551+
self.watched_outputs.lock().unwrap().insert((output.outpoint, output.script_pubkey));
551552
None
552553
}
553554
}

0 commit comments

Comments
 (0)