Skip to content

Commit 3325f90

Browse files
committed
Always return failure in update_monitor after funding spend
Previously, monitor updates were allowed freely even after a funding-spend transaction confirmed. This would allow a race condition where we could receive a payment (including the counterparty revoking their broadcasted state!) and accept it without recourse as long as the ChannelMonitor receives the block first, the full commitment update dance occurs after the block is connected, and before the ChannelManager receives the block. Obviously this is an incredibly contrived race given the counterparty would be risking their full channel balance for it, but its worth fixing nonetheless as it makes the potential ChannelMonitor states simpler to reason about. The test in this commit also tests the behavior changed in the previous commit.
1 parent 0e06f6c commit 3325f90

File tree

2 files changed

+134
-5
lines changed

2 files changed

+134
-5
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 123 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,11 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
700700
// remote monitor out-of-order with regards to the block view.
701701
holder_tx_signed: bool,
702702

703+
// If a spend of the funding output is seen, we set this to true and reject any further
704+
// updates. This prevents any further changes in the offchain state no matter the order
705+
// of block connection between ChannelMonitors and the ChannelManager.
706+
funding_spend_seen: bool,
707+
703708
funding_spend_confirmed: Option<Txid>,
704709
/// The set of HTLCs which have been either claimed or failed on chain and have reached
705710
/// the requisite confirmations on the claim/fail transaction (either ANTI_REORG_DELAY or the
@@ -765,6 +770,7 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
765770
self.outputs_to_watch != other.outputs_to_watch ||
766771
self.lockdown_from_offchain != other.lockdown_from_offchain ||
767772
self.holder_tx_signed != other.holder_tx_signed ||
773+
self.funding_spend_seen != other.funding_spend_seen ||
768774
self.funding_spend_confirmed != other.funding_spend_confirmed ||
769775
self.htlcs_resolved_on_chain != other.htlcs_resolved_on_chain
770776
{
@@ -940,6 +946,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
940946
(1, self.funding_spend_confirmed, option),
941947
(3, self.htlcs_resolved_on_chain, vec_type),
942948
(5, self.pending_monitor_events, vec_type),
949+
(7, self.funding_spend_seen, required),
943950
});
944951

945952
Ok(())
@@ -1038,6 +1045,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
10381045

10391046
lockdown_from_offchain: false,
10401047
holder_tx_signed: false,
1048+
funding_spend_seen: false,
10411049
funding_spend_confirmed: None,
10421050
htlcs_resolved_on_chain: Vec::new(),
10431051

@@ -1843,6 +1851,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18431851
}
18441852
}
18451853
self.latest_update_id = updates.update_id;
1854+
1855+
if ret.is_ok() && self.funding_spend_seen {
1856+
ret = Err(MonitorUpdateError("Counterparty attempted to update commitment after funding was spent"));
1857+
}
18461858
ret
18471859
}
18481860

@@ -2271,6 +2283,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22712283
if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 {
22722284
let mut balance_spendable_csv = None;
22732285
log_info!(logger, "Channel closed by funding output spend in txid {}.", log_bytes!(tx.txid()));
2286+
self.funding_spend_seen = true;
22742287
if (tx.input[0].sequence >> 8*3) as u8 == 0x80 && (tx.lock_time >> 8*3) as u8 == 0x20 {
22752288
let (mut new_outpoints, new_outputs) = self.check_spend_counterparty_transaction(&tx, height, &logger);
22762289
if !new_outputs.1.is_empty() {
@@ -3120,10 +3133,12 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
31203133

31213134
let mut funding_spend_confirmed = None;
31223135
let mut htlcs_resolved_on_chain = Some(Vec::new());
3136+
let mut funding_spend_seen = Some(false);
31233137
read_tlv_fields!(reader, {
31243138
(1, funding_spend_confirmed, option),
31253139
(3, htlcs_resolved_on_chain, vec_type),
31263140
(5, pending_monitor_events, vec_type),
3141+
(7, funding_spend_seen, option),
31273142
});
31283143

31293144
let mut secp_ctx = Secp256k1::new();
@@ -3173,6 +3188,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
31733188

31743189
lockdown_from_offchain,
31753190
holder_tx_signed,
3191+
funding_spend_seen: funding_spend_seen.unwrap(),
31763192
funding_spend_confirmed,
31773193
htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
31783194

@@ -3186,6 +3202,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
31863202

31873203
#[cfg(test)]
31883204
mod tests {
3205+
use bitcoin::blockdata::block::BlockHeader;
31893206
use bitcoin::blockdata::script::{Script, Builder};
31903207
use bitcoin::blockdata::opcodes;
31913208
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType};
@@ -3194,24 +3211,125 @@ mod tests {
31943211
use bitcoin::hashes::Hash;
31953212
use bitcoin::hashes::sha256::Hash as Sha256;
31963213
use bitcoin::hashes::hex::FromHex;
3197-
use bitcoin::hash_types::Txid;
3214+
use bitcoin::hash_types::{BlockHash, Txid};
31983215
use bitcoin::network::constants::Network;
3216+
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
3217+
use bitcoin::secp256k1::Secp256k1;
3218+
31993219
use hex;
3200-
use chain::BestBlock;
3220+
3221+
use super::ChannelMonitorUpdateStep;
3222+
use ::{check_added_monitors, check_closed_broadcast, check_closed_event, check_spends, get_local_commitment_txn, get_monitor, get_route_and_payment_hash, unwrap_send_err};
3223+
use chain::{BestBlock, Confirm};
32013224
use chain::channelmonitor::ChannelMonitor;
32023225
use chain::package::{WEIGHT_OFFERED_HTLC, WEIGHT_RECEIVED_HTLC, WEIGHT_REVOKED_OFFERED_HTLC, WEIGHT_REVOKED_RECEIVED_HTLC, WEIGHT_REVOKED_OUTPUT};
32033226
use chain::transaction::OutPoint;
3227+
use chain::keysinterface::InMemorySigner;
32043228
use ln::{PaymentPreimage, PaymentHash};
32053229
use ln::chan_utils;
32063230
use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
3231+
use ln::channelmanager::PaymentSendFailure;
3232+
use ln::features::InitFeatures;
3233+
use ln::functional_test_utils::*;
32073234
use ln::script::ShutdownScript;
3235+
use util::errors::APIError;
3236+
use util::events::{ClosureReason, MessageSendEventsProvider};
32083237
use util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator};
3209-
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
3210-
use bitcoin::secp256k1::Secp256k1;
3238+
use util::ser::{ReadableArgs, Writeable};
32113239
use sync::{Arc, Mutex};
3212-
use chain::keysinterface::InMemorySigner;
3240+
use io;
32133241
use prelude::*;
32143242

3243+
fn do_test_funding_spend_refuses_updates(use_local_txn: bool) {
3244+
// Previously, monitor updates were allowed freely even after a funding-spend transaction
3245+
// confirmed. This would allow a race condition where we could receive a payment (including
3246+
// the counterparty revoking their broadcasted state!) and accept it without recourse as
3247+
// long as the ChannelMonitor receives the block first, the full commitment update dance
3248+
// occurs after the block is connected, and before the ChannelManager receives the block.
3249+
// Obviously this is an incredibly contrived race given the counterparty would be risking
3250+
// their full channel balance for it, but its worth fixing nonetheless as it makes the
3251+
// potential ChannelMonitor states simpler to reason about.
3252+
//
3253+
// This test checks said behavior, as well as ensuring a ChannelMonitorUpdate with multiple
3254+
// updates is handled correctly in such conditions.
3255+
let chanmon_cfgs = create_chanmon_cfgs(3);
3256+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
3257+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
3258+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
3259+
let channel = create_announced_chan_between_nodes(
3260+
&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
3261+
create_announced_chan_between_nodes(
3262+
&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
3263+
3264+
// Rebalance somewhat
3265+
send_payment(&nodes[0], &[&nodes[1]], 10_000_000);
3266+
3267+
// First route two payments for testing at the end
3268+
let payment_preimage_1 = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000).0;
3269+
let payment_preimage_2 = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000).0;
3270+
3271+
let local_txn = get_local_commitment_txn!(nodes[1], channel.2);
3272+
assert_eq!(local_txn.len(), 1);
3273+
let remote_txn = get_local_commitment_txn!(nodes[0], channel.2);
3274+
assert_eq!(remote_txn.len(), 3); // Commitment and two HTLC-Timeouts
3275+
check_spends!(remote_txn[1], remote_txn[0]);
3276+
check_spends!(remote_txn[2], remote_txn[0]);
3277+
let broadcast_tx = if use_local_txn { &local_txn[0] } else { &remote_txn[0] };
3278+
3279+
// Connect a commitment transaction, but only to the ChainMonitor/ChannelMonitor. The
3280+
// channel is now closed, but the ChannelManager doesn't know that yet.
3281+
let new_header = BlockHeader {
3282+
version: 2, time: 0, bits: 0, nonce: 0,
3283+
prev_blockhash: nodes[0].best_block_info().0,
3284+
merkle_root: Default::default() };
3285+
let conf_height = nodes[0].best_block_info().1 + 1;
3286+
nodes[1].chain_monitor.chain_monitor.transactions_confirmed(&new_header,
3287+
&[(0, broadcast_tx)], conf_height);
3288+
3289+
let (_, pre_update_monitor) = <(BlockHash, ChannelMonitor<InMemorySigner>)>::read(
3290+
&mut io::Cursor::new(&get_monitor!(nodes[1], channel.2).encode()),
3291+
&nodes[1].keys_manager.backing).unwrap();
3292+
3293+
// If the ChannelManager tries to update the channel, however, the ChainMonitor will pass
3294+
// the update through to the ChannelMonitor which will refuse it (as the channel is closed).
3295+
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 100_000);
3296+
unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)),
3297+
true, APIError::ChannelUnavailable { ref err },
3298+
assert!(err.contains("ChannelMonitor storage failure")));
3299+
check_added_monitors!(nodes[1], 2); // After the failure we generate a close-channel monitor update
3300+
check_closed_broadcast!(nodes[1], true);
3301+
check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() });
3302+
3303+
let monitor_updates = nodes[1].chain_monitor.monitor_updates.lock().unwrap();
3304+
let mut replay_update = monitor_updates.get(&channel.2).unwrap().iter().rev().skip(1).next().unwrap().clone();
3305+
assert_eq!(replay_update.updates.len(), 1);
3306+
if let ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } = replay_update.updates[0] {
3307+
} else { panic!(); }
3308+
replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage: payment_preimage_1 });
3309+
replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage: payment_preimage_2 });
3310+
3311+
let broadcaster = TestBroadcaster::new(Arc::clone(&nodes[1].blocks));
3312+
assert!(
3313+
pre_update_monitor.update_monitor(&replay_update, &&broadcaster, &&chanmon_cfgs[1].fee_estimator, &nodes[1].logger)
3314+
.is_err());
3315+
// Even though we error'd on the first update, we should still have generated an HTLC claim
3316+
// transaction
3317+
let txn_broadcasted = broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
3318+
assert!(txn_broadcasted.len() >= 2);
3319+
let htlc_txn = txn_broadcasted.iter().filter(|tx| {
3320+
assert_eq!(tx.input.len(), 1);
3321+
tx.input[0].previous_output.txid == broadcast_tx.txid()
3322+
}).collect::<Vec<_>>();
3323+
assert_eq!(htlc_txn.len(), 2);
3324+
check_spends!(htlc_txn[0], broadcast_tx);
3325+
check_spends!(htlc_txn[1], broadcast_tx);
3326+
}
3327+
#[test]
3328+
fn test_funding_spend_refuses_updates() {
3329+
do_test_funding_spend_refuses_updates(true);
3330+
do_test_funding_spend_refuses_updates(false);
3331+
}
3332+
32153333
#[test]
32163334
fn test_prune_preimages() {
32173335
let secp_ctx = Secp256k1::new();

lightning/src/util/test_utils.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ impl keysinterface::KeysInterface for OnlyReadsKeysInterface {
8989

9090
pub struct TestChainMonitor<'a> {
9191
pub added_monitors: Mutex<Vec<(OutPoint, channelmonitor::ChannelMonitor<EnforcingSigner>)>>,
92+
pub monitor_updates: Mutex<HashMap<[u8; 32], Vec<channelmonitor::ChannelMonitorUpdate>>>,
9293
pub latest_monitor_update_id: Mutex<HashMap<[u8; 32], (OutPoint, u64, MonitorUpdateId)>>,
9394
pub chain_monitor: chainmonitor::ChainMonitor<EnforcingSigner, &'a TestChainSource, &'a chaininterface::BroadcasterInterface, &'a TestFeeEstimator, &'a TestLogger, &'a chainmonitor::Persist<EnforcingSigner>>,
9495
pub keys_manager: &'a TestKeysInterface,
@@ -101,6 +102,7 @@ impl<'a> TestChainMonitor<'a> {
101102
pub fn new(chain_source: Option<&'a TestChainSource>, broadcaster: &'a chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator, persister: &'a chainmonitor::Persist<EnforcingSigner>, keys_manager: &'a TestKeysInterface) -> Self {
102103
Self {
103104
added_monitors: Mutex::new(Vec::new()),
105+
monitor_updates: Mutex::new(HashMap::new()),
104106
latest_monitor_update_id: Mutex::new(HashMap::new()),
105107
chain_monitor: chainmonitor::ChainMonitor::new(chain_source, broadcaster, logger, fee_estimator, persister),
106108
keys_manager,
@@ -130,6 +132,8 @@ impl<'a> chain::Watch<EnforcingSigner> for TestChainMonitor<'a> {
130132
assert!(channelmonitor::ChannelMonitorUpdate::read(
131133
&mut io::Cursor::new(&w.0)).unwrap() == update);
132134

135+
self.monitor_updates.lock().unwrap().entry(funding_txo.to_channel_id()).or_insert(Vec::new()).push(update.clone());
136+
133137
if let Some(exp) = self.expect_channel_force_closed.lock().unwrap().take() {
134138
assert_eq!(funding_txo.to_channel_id(), exp.0);
135139
assert_eq!(update.updates.len(), 1);
@@ -209,6 +213,13 @@ pub struct TestBroadcaster {
209213
pub txn_broadcasted: Mutex<Vec<Transaction>>,
210214
pub blocks: Arc<Mutex<Vec<(BlockHeader, u32)>>>,
211215
}
216+
217+
impl TestBroadcaster {
218+
pub fn new(blocks: Arc<Mutex<Vec<(BlockHeader, u32)>>>) -> TestBroadcaster {
219+
TestBroadcaster { txn_broadcasted: Mutex::new(Vec::new()), blocks }
220+
}
221+
}
222+
212223
impl chaininterface::BroadcasterInterface for TestBroadcaster {
213224
fn broadcast_transaction(&self, tx: &Transaction) {
214225
assert!(tx.lock_time < 1_500_000_000);

0 commit comments

Comments
 (0)