Skip to content

Commit ae8bd1b

Browse files
committed
Fix and test simple remote-revoked-commitment-output claiming
1 parent d4ba4af commit ae8bd1b

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/ln/channelmanager.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3422,6 +3422,13 @@ mod tests {
34223422
let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
34233423
// Get the will-be-revoked local txn from nodes[0]
34243424
let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone();
3425+
assert_eq!(revoked_local_txn.len(), 2); // First commitment tx, then HTLC tx
3426+
assert_eq!(revoked_local_txn[0].input.len(), 1);
3427+
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.txid());
3428+
assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to 0 are present
3429+
assert_eq!(revoked_local_txn[1].input.len(), 1);
3430+
assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].txid());
3431+
assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), 133); // HTLC-Timeout
34253432
// Revoke the old state
34263433
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
34273434

@@ -3432,7 +3439,7 @@ mod tests {
34323439
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
34333440
assert_eq!(node_txn.len(), 3);
34343441
assert_eq!(node_txn.pop().unwrap(), node_txn[0]); // An outpoint registration will result in a 2nd block_connected
3435-
assert_eq!(node_txn[0].input.len(), 1);
3442+
assert_eq!(node_txn[0].input.len(), 2); // We should claim the revoked output and the HTLC output
34363443

34373444
let mut funding_tx_map = HashMap::new();
34383445
funding_tx_map.insert(revoked_local_txn[0].txid(), revoked_local_txn[0].clone());
@@ -3453,6 +3460,40 @@ mod tests {
34533460
}
34543461

34553462
#[test]
3463+
fn revoked_output_claim() {
3464+
// Simple test to ensure a node will claim a revoked output when a stale remote commitment
3465+
// transaction is broadcast by its counterparty
3466+
let nodes = create_network(2);
3467+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
3468+
// node[0] is gonna to revoke an old state thus node[1] should be able to claim the revoked output
3469+
let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
3470+
assert_eq!(revoked_local_txn.len(), 1);
3471+
// Only output is the full channel value back to nodes[0]:
3472+
assert_eq!(revoked_local_txn[0].output.len(), 1);
3473+
// Send a payment through, updating everyone's latest commitment txn
3474+
send_payment(&nodes[0], &vec!(&nodes[1])[..], 5000000);
3475+
3476+
// Inform nodes[1] that nodes[0] broadcast a stale tx
3477+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
3478+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
3479+
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
3480+
assert_eq!(node_txn.len(), 3); // nodes[1] will broadcast justice tx twice, and its own local state once
3481+
3482+
assert_eq!(node_txn[0], node_txn[2]);
3483+
3484+
let mut revoked_tx_map = HashMap::new();
3485+
revoked_tx_map.insert(revoked_local_txn[0].txid(), revoked_local_txn[0].clone());
3486+
node_txn[0].verify(&revoked_tx_map).unwrap();
3487+
3488+
revoked_tx_map.clear();
3489+
revoked_tx_map.insert(chan_1.3.txid(), chan_1.3.clone());
3490+
node_txn[1].verify(&revoked_tx_map).unwrap();
3491+
3492+
// Inform nodes[0] that a watchtower cheated on its behalf, so it will force-close the chan
3493+
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
3494+
get_announce_close_broadcast_events(&nodes, 0, 1);
3495+
}
3496+
34563497
fn test_htlc_ignore_latest_remote_commitment() {
34573498
// Test that HTLC transactions spending the latest remote commitment transaction are simply
34583499
// ignored if we cannot claim them. This originally tickled an invalid unwrap().

src/ln/channelmonitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ impl ChannelMonitor {
759759
ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &htlc_base_key)))
760760
},
761761
};
762-
let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.delayed_payment_base_key));
762+
let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.their_delayed_payment_base_key.unwrap()));
763763
let a_htlc_key = match self.their_htlc_base_key {
764764
None => return (txn_to_broadcast, (commitment_txid, watch_outputs)),
765765
Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &their_htlc_base_key)),

0 commit comments

Comments
 (0)