Skip to content

Commit e9a0ab2

Browse files
author
Antoine Riard
committed
Add transaction index in watch_outputs
Previously, outputs were monitored based on txid and an index yelled from an enumeration over the returned selected outputs by monitoring code. This is broken we don't have a guarantee that HTLC outputs are ranking first after introduction of anchor outputs.
1 parent cd13364 commit e9a0ab2

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

lightning/src/ln/channelmonitor.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync
191191
let txn_outputs = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
192192

193193
for (ref txid, ref outputs) in txn_outputs {
194-
for (idx, output) in outputs.iter().enumerate() {
195-
self.chain_monitor.install_watch_outpoint((txid.clone(), idx as u32), &output.script_pubkey);
194+
for (idx, script) in outputs.iter() {
195+
self.chain_monitor.install_watch_outpoint((txid.clone(), *idx), &script.script_pubkey);
196196
}
197197
}
198198
}
@@ -241,8 +241,8 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
241241
self.chain_monitor.install_watch_tx(&funding_txo.0.txid, &funding_txo.1);
242242
self.chain_monitor.install_watch_outpoint((funding_txo.0.txid, funding_txo.0.index as u32), &funding_txo.1);
243243
for (txid, outputs) in monitor.get_outputs_to_watch().iter() {
244-
for (idx, script) in outputs.iter().enumerate() {
245-
self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
244+
for (idx, script) in outputs.iter() {
245+
self.chain_monitor.install_watch_outpoint((*txid, *idx), script);
246246
}
247247
}
248248
}
@@ -789,7 +789,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
789789
// interface knows about the TXOs that we want to be notified of spends of. We could probably
790790
// be smart and derive them from the above storage fields, but its much simpler and more
791791
// Obviously Correct (tm) if we just keep track of them explicitly.
792-
outputs_to_watch: HashMap<Txid, Vec<Script>>,
792+
outputs_to_watch: HashMap<Txid, Vec<(u32, Script)>>,
793793

794794
#[cfg(test)]
795795
pub onchain_tx_handler: OnchainTxHandler<ChanSigner>,
@@ -1095,10 +1095,11 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
10951095
}
10961096

10971097
(self.outputs_to_watch.len() as u64).write(writer)?;
1098-
for (txid, output_scripts) in self.outputs_to_watch.iter() {
1098+
for (txid, idx_scripts) in self.outputs_to_watch.iter() {
10991099
txid.write(writer)?;
1100-
(output_scripts.len() as u64).write(writer)?;
1101-
for script in output_scripts.iter() {
1100+
(idx_scripts.len() as u64).write(writer)?;
1101+
for (idx, script) in idx_scripts.iter() {
1102+
idx.write(writer)?;
11021103
script.write(writer)?;
11031104
}
11041105
}
@@ -1417,7 +1418,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14171418

14181419
/// Gets a list of txids, with their output scripts (in the order they appear in the
14191420
/// transaction), which we must learn about spends of via block_connected().
1420-
pub fn get_outputs_to_watch(&self) -> &HashMap<Txid, Vec<Script>> {
1421+
pub fn get_outputs_to_watch(&self) -> &HashMap<Txid, Vec<(u32, Script)>> {
14211422
&self.outputs_to_watch
14221423
}
14231424

@@ -1478,7 +1479,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14781479
/// HTLC-Success/HTLC-Timeout transactions.
14791480
/// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
14801481
/// revoked remote commitment tx
1481-
fn check_spend_remote_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, (Txid, Vec<TxOut>)) where L::Target: Logger {
1482+
fn check_spend_remote_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, (Txid, Vec<(u32, TxOut)>)) where L::Target: Logger {
14821483
// Most secp and related errors trying to create keys means we have no hope of constructing
14831484
// a spend transaction...so we return no transactions to broadcast
14841485
let mut claimable_outpoints = Vec::new();
@@ -1533,7 +1534,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
15331534
if !claimable_outpoints.is_empty() || per_commitment_option.is_some() { // ie we're confident this is actually ours
15341535
// We're definitely a remote commitment transaction!
15351536
log_trace!(logger, "Got broadcast of revoked remote commitment transaction, going to generate general spend tx with {} inputs", claimable_outpoints.len());
1536-
watch_outputs.append(&mut tx.output.clone());
1537+
for (idx, outp) in tx.output.iter().enumerate() {
1538+
watch_outputs.push((idx as u32, outp.clone()));
1539+
}
15371540
self.remote_commitment_txn_on_chain.insert(commitment_txid, (commitment_number, tx.output.iter().map(|output| { output.script_pubkey.clone() }).collect()));
15381541

15391542
macro_rules! check_htlc_fails {
@@ -1580,7 +1583,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
15801583
// already processed the block, resulting in the remote_commitment_txn_on_chain entry
15811584
// not being generated by the above conditional. Thus, to be safe, we go ahead and
15821585
// insert it here.
1583-
watch_outputs.append(&mut tx.output.clone());
1586+
for (idx, outp) in tx.output.iter().enumerate() {
1587+
watch_outputs.push((idx as u32, outp.clone()));
1588+
}
15841589
self.remote_commitment_txn_on_chain.insert(commitment_txid, (commitment_number, tx.output.iter().map(|output| { output.script_pubkey.clone() }).collect()));
15851590

15861591
log_trace!(logger, "Got broadcast of non-revoked remote commitment transaction {}", commitment_txid);
@@ -1670,7 +1675,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
16701675
}
16711676

16721677
/// Attempts to claim a remote HTLC-Success/HTLC-Timeout's outputs using the revocation key
1673-
fn check_spend_remote_htlc<L: Deref>(&mut self, tx: &Transaction, commitment_number: u64, height: u32, logger: &L) -> (Vec<ClaimRequest>, Option<(Txid, Vec<TxOut>)>) where L::Target: Logger {
1678+
fn check_spend_remote_htlc<L: Deref>(&mut self, tx: &Transaction, commitment_number: u64, height: u32, logger: &L) -> (Vec<ClaimRequest>, Option<(Txid, Vec<(u32, TxOut)>)>) where L::Target: Logger {
16741679
let htlc_txid = tx.txid();
16751680
if tx.input.len() != 1 || tx.output.len() != 1 || tx.input[0].witness.len() != 5 {
16761681
return (Vec::new(), None)
@@ -1692,10 +1697,11 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
16921697
log_trace!(logger, "Remote HTLC broadcast {}:{}", htlc_txid, 0);
16931698
let witness_data = InputMaterial::Revoked { per_commitment_point, remote_delayed_payment_base_key: self.remote_tx_cache.remote_delayed_payment_base_key, remote_htlc_base_key: self.remote_tx_cache.remote_htlc_base_key, per_commitment_key, input_descriptor: InputDescriptors::RevokedOutput, amount: tx.output[0].value, htlc: None, on_remote_tx_csv: self.remote_tx_cache.on_remote_tx_csv };
16941699
let claimable_outpoints = vec!(ClaimRequest { absolute_timelock: height + self.remote_tx_cache.on_remote_tx_csv as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: htlc_txid, vout: 0}, witness_data });
1695-
(claimable_outpoints, Some((htlc_txid, tx.output.clone())))
1700+
let outputs = vec![(0, tx.output[0].clone())];
1701+
(claimable_outpoints, Some((htlc_txid, outputs)))
16961702
}
16971703

1698-
fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec<ClaimRequest>, Vec<TxOut>, Option<(Script, PublicKey, PublicKey)>) {
1704+
fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec<ClaimRequest>, Vec<(u32, TxOut)>, Option<(Script, PublicKey, PublicKey)>) {
16991705
let mut claim_requests = Vec::with_capacity(local_tx.htlc_outputs.len());
17001706
let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
17011707

@@ -1716,7 +1722,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
17161722
} else { None },
17171723
amount: htlc.amount_msat,
17181724
}});
1719-
watch_outputs.push(commitment_tx.output[transaction_output_index as usize].clone());
1725+
watch_outputs.push((transaction_output_index, commitment_tx.output[transaction_output_index as usize].clone()));
17201726
}
17211727
}
17221728

@@ -1726,7 +1732,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
17261732
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
17271733
/// revoked using data in local_claimable_outpoints.
17281734
/// Should not be used if check_spend_revoked_transaction succeeds.
1729-
fn check_spend_local_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, (Txid, Vec<TxOut>)) where L::Target: Logger {
1735+
fn check_spend_local_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, (Txid, Vec<(u32, TxOut)>)) where L::Target: Logger {
17301736
let commitment_txid = tx.txid();
17311737
let mut claim_requests = Vec::new();
17321738
let mut watch_outputs = Vec::new();
@@ -1870,7 +1876,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
18701876
/// Eventually this should be pub and, roughly, implement ChainListener, however this requires
18711877
/// &mut self, as well as returns new spendable outputs and outpoints to watch for spending of
18721878
/// on-chain.
1873-
fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
1879+
fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<(u32, TxOut)>)>
18741880
where B::Target: BroadcasterInterface,
18751881
F::Target: FeeEstimator,
18761882
L::Target: Logger,
@@ -1962,8 +1968,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
19621968
self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator, &*logger);
19631969

19641970
self.last_block_hash = block_hash.clone();
1965-
for &(ref txid, ref output_scripts) in watch_outputs.iter() {
1966-
self.outputs_to_watch.insert(txid.clone(), output_scripts.iter().map(|o| o.script_pubkey.clone()).collect());
1971+
for &(ref txid, ref idx_scripts) in watch_outputs.iter() {
1972+
self.outputs_to_watch.insert(txid.clone(), idx_scripts.iter().map(|o| (o.0, o.1.script_pubkey.clone())).collect());
19671973
}
19681974

19691975
watch_outputs
@@ -2460,13 +2466,13 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for (BlockHash, ChannelMonitor
24602466
}
24612467

24622468
let outputs_to_watch_len: u64 = Readable::read(reader)?;
2463-
let mut outputs_to_watch = HashMap::with_capacity(cmp::min(outputs_to_watch_len as usize, MAX_ALLOC_SIZE / (mem::size_of::<Txid>() + mem::size_of::<Vec<Script>>())));
2469+
let mut outputs_to_watch = HashMap::with_capacity(cmp::min(outputs_to_watch_len as usize, MAX_ALLOC_SIZE / (mem::size_of::<Txid>() + mem::size_of::<u32>() + mem::size_of::<Vec<Script>>())));
24642470
for _ in 0..outputs_to_watch_len {
24652471
let txid = Readable::read(reader)?;
24662472
let outputs_len: u64 = Readable::read(reader)?;
2467-
let mut outputs = Vec::with_capacity(cmp::min(outputs_len as usize, MAX_ALLOC_SIZE / mem::size_of::<Script>()));
2473+
let mut outputs = Vec::with_capacity(cmp::min(outputs_len as usize, MAX_ALLOC_SIZE / (mem::size_of::<u32>() + mem::size_of::<Script>())));
24682474
for _ in 0..outputs_len {
2469-
outputs.push(Readable::read(reader)?);
2475+
outputs.push((Readable::read(reader)?, Readable::read(reader)?));
24702476
}
24712477
if let Some(_) = outputs_to_watch.insert(txid, outputs) {
24722478
return Err(DecodeError::InvalidValue);

0 commit comments

Comments
 (0)