Skip to content

Commit 796e0ad

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 250f30b commit 796e0ad

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
@@ -32,7 +32,7 @@
3232
use bitcoin::blockdata::block::{Block, BlockHeader};
3333

3434
use chain;
35-
use chain::Filter;
35+
use chain::{Filter, WatchedOutput};
3636
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
3737
use chain::channelmonitor;
3838
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist};
@@ -98,9 +98,14 @@ where C::Target: chain::Filter,
9898
let mut txn_outputs = monitor.block_connected(header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
9999

100100
if let Some(ref chain_source) = self.chain_source {
101+
let block_hash = header.block_hash();
101102
for (txid, outputs) in txn_outputs.drain(..) {
102103
for (idx, output) in outputs.iter() {
103-
chain_source.register_output(&OutPoint { txid, index: *idx as u16 }, &output.script_pubkey);
104+
chain_source.register_output(WatchedOutput {
105+
block_hash: Some(block_hash),
106+
outpoint: OutPoint { txid, index: *idx as u16 },
107+
script_pubkey: output.script_pubkey.clone(),
108+
});
104109
}
105110
}
106111
}

lightning/src/chain/channelmonitor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLC
4242
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
4343
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
4444
use chain;
45+
use chain::WatchedOutput;
4546
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
4647
use chain::transaction::{OutPoint, TransactionData};
4748
use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface};
@@ -1180,7 +1181,11 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
11801181
for (txid, outputs) in lock.get_outputs_to_watch().iter() {
11811182
for (index, script_pubkey) in outputs.iter() {
11821183
assert!(*index <= u16::max_value() as u32);
1183-
filter.register_output(&OutPoint { txid: *txid, index: *index as u16 }, script_pubkey);
1184+
filter.register_output(WatchedOutput {
1185+
block_hash: None,
1186+
outpoint: OutPoint { txid: *txid, index: *index as u16 },
1187+
script_pubkey: script_pubkey.clone(),
1188+
});
11841189
}
11851190
}
11861191
}

lightning/src/chain/mod.rs

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

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

143165
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;
@@ -545,8 +546,8 @@ impl chain::Filter for TestChainSource {
545546
self.watched_txn.lock().unwrap().insert((*txid, script_pubkey.clone()));
546547
}
547548

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

0 commit comments

Comments
 (0)