Skip to content

Commit fe40e9a

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

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

src/ln/channelmanager.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3422,6 +3422,12 @@ 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());
34253431
// Revoke the old state
34263432
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
34273433

@@ -3432,7 +3438,7 @@ mod tests {
34323438
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
34333439
assert_eq!(node_txn.len(), 3);
34343440
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);
3441+
assert_eq!(node_txn[0].input.len(), 2); // We should claim the revoked output and the HTLC output
34363442

34373443
let mut funding_tx_map = HashMap::new();
34383444
funding_tx_map.insert(revoked_local_txn[0].txid(), revoked_local_txn[0].clone());
@@ -3453,6 +3459,40 @@ mod tests {
34533459
}
34543460

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