Skip to content

Add test_claim_on_remote_revoked_sizeable_push_msat #259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 23, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 109 additions & 107 deletions src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7588,8 +7588,8 @@ mod tests {
} else { panic!("Unexpected result"); }
}

macro_rules! check_dynamic_output_p2wsh {
($node: expr) => {
macro_rules! check_spendable_outputs {
($node: expr, $der_idx: expr) => {
{
let events = $node.chan_monitor.simple_monitor.get_and_clear_pending_events();
let mut txn = Vec::new();
Expand All @@ -7598,6 +7598,33 @@ mod tests {
Event::SpendableOutputs { ref outputs } => {
for outp in outputs {
match *outp {
SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
let input = TxIn {
previous_output: outpoint.clone(),
script_sig: Script::new(),
sequence: 0,
witness: Vec::new(),
};
let outp = TxOut {
script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(),
value: output.value,
};
let mut spend_tx = Transaction {
version: 2,
lock_time: 0,
input: vec![input],
output: vec![outp],
};
let secp_ctx = Secp256k1::new();
let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &key);
let witness_script = Address::p2pkh(&remotepubkey, Network::Testnet).script_pubkey();
let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
let remotesig = secp_ctx.sign(&sighash, key);
spend_tx.input[0].witness.push(remotesig.serialize_der(&secp_ctx).to_vec());
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
txn.push(spend_tx);
},
SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref key, ref witness_script, ref to_self_delay, ref output } => {
let input = TxIn {
previous_output: outpoint.clone(),
Expand All @@ -7624,29 +7651,8 @@ mod tests {
spend_tx.input[0].witness.push(witness_script.clone().into_bytes());
txn.push(spend_tx);
},
_ => panic!("Unexpected event"),
}
}
},
_ => panic!("Unexpected event"),
};
}
txn
}
}
}

macro_rules! check_dynamic_output_p2wpkh {
($node: expr) => {
{
let events = $node.chan_monitor.simple_monitor.get_and_clear_pending_events();
let mut txn = Vec::new();
for event in events {
match event {
Event::SpendableOutputs { ref outputs } => {
for outp in outputs {
match *outp {
SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => {
let secp_ctx = Secp256k1::new();
let input = TxIn {
previous_output: outpoint.clone(),
script_sig: Script::new(),
Expand All @@ -7661,19 +7667,28 @@ mod tests {
version: 2,
lock_time: 0,
input: vec![input],
output: vec![outp],
output: vec![outp.clone()],
};
let secp_ctx = Secp256k1::new();
let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &key);
let witness_script = Address::p2pkh(&remotepubkey, Network::Testnet).script_pubkey();
let secret = {
match ExtendedPrivKey::new_master(&secp_ctx, Network::Testnet, &$node.node_seed) {
Ok(master_key) => {
match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx($der_idx)) {
Ok(key) => key,
Err(_) => panic!("Your RNG is busted"),
}
}
Err(_) => panic!("Your rng is busted"),
}
};
let pubkey = ExtendedPubKey::from_private(&secp_ctx, &secret).public_key;
let witness_script = Address::p2pkh(&pubkey, Network::Testnet).script_pubkey();
let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
let remotesig = secp_ctx.sign(&sighash, key);
spend_tx.input[0].witness.push(remotesig.serialize_der(&secp_ctx).to_vec());
let sig = secp_ctx.sign(&sighash, &secret.secret_key);
spend_tx.input[0].witness.push(sig.serialize_der(&secp_ctx).to_vec());
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
spend_tx.input[0].witness.push(pubkey.serialize().to_vec());
txn.push(spend_tx);
},
_ => panic!("Unexpected event"),
}
}
},
Expand All @@ -7685,57 +7700,6 @@ mod tests {
}
}

macro_rules! check_static_output {
($event: expr, $node: expr, $event_idx: expr, $output_idx: expr, $der_idx: expr, $idx_node: expr) => {
match $event[$event_idx] {
Event::SpendableOutputs { ref outputs } => {
match outputs[$output_idx] {
SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => {
let secp_ctx = Secp256k1::new();
let input = TxIn {
previous_output: outpoint.clone(),
script_sig: Script::new(),
sequence: 0,
witness: Vec::new(),
};
let outp = TxOut {
script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(),
value: output.value,
};
let mut spend_tx = Transaction {
version: 2,
lock_time: 0,
input: vec![input],
output: vec![outp.clone()],
};
let secret = {
match ExtendedPrivKey::new_master(&secp_ctx, Network::Testnet, &$node[$idx_node].node_seed) {
Ok(master_key) => {
match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx($der_idx)) {
Ok(key) => key,
Err(_) => panic!("Your RNG is busted"),
}
}
Err(_) => panic!("Your rng is busted"),
}
};
let pubkey = ExtendedPubKey::from_private(&secp_ctx, &secret).public_key;
let witness_script = Address::p2pkh(&pubkey, Network::Testnet).script_pubkey();
let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
let sig = secp_ctx.sign(&sighash, &secret.secret_key);
spend_tx.input[0].witness.push(sig.serialize_der(&secp_ctx).to_vec());
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
spend_tx.input[0].witness.push(pubkey.serialize().to_vec());
spend_tx
},
_ => panic!("Unexpected event !"),
}
},
_ => panic!("Unexpected event !"),
};
}
}

#[test]
fn test_claim_sizeable_push_msat() {
// Incidentally test SpendableOutput event generation due to detection of to_local output on commitment tx
Expand All @@ -7755,14 +7719,14 @@ mod tests {

let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
let spend_txn = check_dynamic_output_p2wsh!(nodes[1]);
let spend_txn = check_spendable_outputs!(nodes[1], 1);
assert_eq!(spend_txn.len(), 1);
check_spends!(spend_txn[0], node_txn[0].clone());
}

#[test]
fn test_claim_on_remote_sizeable_push_msat() {
// Same test as precedent, just test on remote commitment tx, as per_commitment_point registration changes following you're funder/fundee and
// Same test as previous, just test on remote commitment tx, as per_commitment_point registration changes following you're funder/fundee and
// to_remote output is encumbered by a P2WPKH

let nodes = create_network(2);
Expand All @@ -7786,12 +7750,42 @@ mod tests {
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
_ => panic!("Unexpected event"),
}
let spend_txn = check_dynamic_output_p2wpkh!(nodes[1]);
let spend_txn = check_spendable_outputs!(nodes[1], 1);
assert_eq!(spend_txn.len(), 2);
assert_eq!(spend_txn[0], spend_txn[1]);
check_spends!(spend_txn[0], node_txn[0].clone());
}

#[test]
fn test_claim_on_remote_revoked_sizeable_push_msat() {
// Same test as previous, just test on remote revoked commitment tx, as per_commitment_point registration changes following you're funder/fundee and
// to_remote output is encumbered by a P2WPKH

let nodes = create_network(2);

let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 59000000);
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());

claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
match events[0] {
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
_ => panic!("Unexpected event"),
}
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
let spend_txn = check_spendable_outputs!(nodes[1], 1);
assert_eq!(spend_txn.len(), 4);
assert_eq!(spend_txn[0], spend_txn[2]); // to_remote output on revoked remote commitment_tx
check_spends!(spend_txn[0], revoked_local_txn[0].clone());
assert_eq!(spend_txn[1], spend_txn[3]); // to_local output on local commitment tx
check_spends!(spend_txn[1], node_txn[0].clone());
}

#[test]
fn test_static_spendable_outputs_preimage_tx() {
let nodes = create_network(2);
Expand Down Expand Up @@ -7827,9 +7821,10 @@ mod tests {
assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), 133);
check_spends!(node_txn[1], chan_1.3.clone());

let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events();
let spend_tx = check_static_output!(events, nodes, 0, 0, 1, 1);
check_spends!(spend_tx, node_txn[0].clone());
let spend_txn = check_spendable_outputs!(nodes[1], 1); // , 0, 0, 1, 1);
assert_eq!(spend_txn.len(), 2);
assert_eq!(spend_txn[0], spend_txn[1]);
check_spends!(spend_txn[0], node_txn[0].clone());
}

#[test]
Expand Down Expand Up @@ -7859,9 +7854,10 @@ mod tests {
assert_eq!(node_txn[0].input.len(), 2);
check_spends!(node_txn[0], revoked_local_txn[0].clone());

let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events();
let spend_tx = check_static_output!(events, nodes, 0, 0, 1, 1);
check_spends!(spend_tx, node_txn[0].clone());
let spend_txn = check_spendable_outputs!(nodes[1], 1);
assert_eq!(spend_txn.len(), 2);
assert_eq!(spend_txn[0], spend_txn[1]);
check_spends!(spend_txn[0], node_txn[0].clone());
}

#[test]
Expand Down Expand Up @@ -7905,10 +7901,12 @@ mod tests {
assert_eq!(node_txn[3].input.len(), 1);
check_spends!(node_txn[3], revoked_htlc_txn[0].clone());

let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events();
// Check B's ChannelMonitor was able to generate the right spendable output descriptor
let spend_tx = check_static_output!(events, nodes, 1, 1, 1, 1);
check_spends!(spend_tx, node_txn[3].clone());
let spend_txn = check_spendable_outputs!(nodes[1], 1);
assert_eq!(spend_txn.len(), 3);
assert_eq!(spend_txn[0], spend_txn[1]);
check_spends!(spend_txn[0], node_txn[0].clone());
check_spends!(spend_txn[2], node_txn[3].clone());
}

#[test]
Expand Down Expand Up @@ -7953,10 +7951,14 @@ mod tests {
assert_eq!(node_txn[3].input.len(), 1);
check_spends!(node_txn[3], revoked_htlc_txn[0].clone());

let events = nodes[0].chan_monitor.simple_monitor.get_and_clear_pending_events();
// Check A's ChannelMonitor was able to generate the right spendable output descriptor
let spend_tx = check_static_output!(events, nodes, 1, 2, 1, 0);
check_spends!(spend_tx, node_txn[3].clone());
let spend_txn = check_spendable_outputs!(nodes[0], 1);
assert_eq!(spend_txn.len(), 5);
assert_eq!(spend_txn[0], spend_txn[2]);
assert_eq!(spend_txn[1], spend_txn[3]);
check_spends!(spend_txn[0], revoked_local_txn[0].clone()); // spending to_remote output from revoked local tx
check_spends!(spend_txn[1], node_txn[2].clone()); // spending justice tx output from revoked local tx htlc received output
check_spends!(spend_txn[4], node_txn[3].clone()); // spending justice tx output on htlc success tx
}

#[test]
Expand Down Expand Up @@ -7991,7 +7993,7 @@ mod tests {
check_spends!(node_txn[0], local_txn[0].clone());

// Verify that B is able to spend its own HTLC-Success tx thanks to spendable output event given back by its ChannelMonitor
let spend_txn = check_dynamic_output_p2wsh!(nodes[1]);
let spend_txn = check_spendable_outputs!(nodes[1], 1);
assert_eq!(spend_txn.len(), 1);
check_spends!(spend_txn[0], node_txn[0].clone());
}
Expand Down Expand Up @@ -8022,7 +8024,7 @@ mod tests {
check_spends!(node_txn[0], local_txn[0].clone());

// Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor
let spend_txn = check_dynamic_output_p2wsh!(nodes[0]);
let spend_txn = check_spendable_outputs!(nodes[0], 1);
assert_eq!(spend_txn.len(), 4);
assert_eq!(spend_txn[0], spend_txn[2]);
assert_eq!(spend_txn[1], spend_txn[3]);
Expand All @@ -8041,13 +8043,13 @@ mod tests {

let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
let events = nodes[0].chan_monitor.simple_monitor.get_and_clear_pending_events();
let spend_tx = check_static_output!(events, nodes, 0, 0, 2, 0);
check_spends!(spend_tx, closing_tx.clone());
let spend_txn = check_spendable_outputs!(nodes[0], 2);
assert_eq!(spend_txn.len(), 1);
check_spends!(spend_txn[0], closing_tx.clone());

nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events();
let spend_tx = check_static_output!(events, nodes, 0, 0, 2, 1);
check_spends!(spend_tx, closing_tx);
let spend_txn = check_spendable_outputs!(nodes[1], 2);
assert_eq!(spend_txn.len(), 1);
check_spends!(spend_txn[0], closing_tx);
}
}