Skip to content

Commit 81e358c

Browse files
author
Antoine Riard
committed
Add test_key_derivation_params
`to_local` output or remote output on remote commitment transaction needs a channel keys to be spent. As per-channel keys are derived from KeysManager seed and per-channel secrets those must be backed up by any descriptor bookmarking for latter spend. We test that generating a new KeysManager loaded with such backed-up seed/per-channel secrets return the correct keys for spending a `to_local` output.
1 parent d0c5e9c commit 81e358c

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

lightning/src/ln/functional_tests.rs

+73
Original file line numberDiff line numberDiff line change
@@ -5280,6 +5280,79 @@ fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() {
52805280
check_spends!(spend_txn[2], htlc_timeout);
52815281
}
52825282

5283+
#[test]
5284+
fn test_key_derivation_params() {
5285+
// This test is a copy of test_dynamic_spendable_outputs_local_htlc_timeout_tx, with
5286+
// a key manager rotation to test that key_derivation_params returned in DynamicOutputP2WSH
5287+
// let us re-derive the channel key set to then derive a delayed_payment_key.
5288+
5289+
let chanmon_cfgs = create_chanmon_cfgs(3);
5290+
5291+
// We manually create the node configuration to backup the seed.
5292+
let mut rng = thread_rng();
5293+
let mut seed = [0; 32];
5294+
rng.fill_bytes(&mut seed);
5295+
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
5296+
let chan_monitor = test_utils::TestChannelMonitor::new(&chanmon_cfgs[0].chain_monitor, &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator);
5297+
let node = NodeCfg { chain_monitor: &chanmon_cfgs[0].chain_monitor, logger: &chanmon_cfgs[0].logger, tx_broadcaster: &chanmon_cfgs[0].tx_broadcaster, fee_estimator: &chanmon_cfgs[0].fee_estimator, chan_monitor, keys_manager, node_seed: seed };
5298+
let mut node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
5299+
node_cfgs.remove(0);
5300+
node_cfgs.insert(0, node);
5301+
5302+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
5303+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
5304+
5305+
// Create some initial channels
5306+
// Create a dummy channel to advance index by one and thus test re-derivation correctness
5307+
// for node 0
5308+
let chan_0 = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known());
5309+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
5310+
assert_ne!(chan_0.3.output[0].script_pubkey, chan_1.3.output[0].script_pubkey);
5311+
5312+
let (_, our_payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000);
5313+
let local_txn_0 = get_local_commitment_txn!(nodes[0], chan_0.2);
5314+
let local_txn_1 = get_local_commitment_txn!(nodes[0], chan_1.2);
5315+
assert_eq!(local_txn_1[0].input.len(), 1);
5316+
check_spends!(local_txn_1[0], chan_1.3);
5317+
5318+
// We check funding pubkey are unique
5319+
let (from_0_funding_key_0, from_0_funding_key_1) = (PublicKey::from_slice(&local_txn_0[0].input[0].witness[3][2..35]), PublicKey::from_slice(&local_txn_0[0].input[0].witness[3][36..69]));
5320+
let (from_1_funding_key_0, from_1_funding_key_1) = (PublicKey::from_slice(&local_txn_1[0].input[0].witness[3][2..35]), PublicKey::from_slice(&local_txn_1[0].input[0].witness[3][36..69]));
5321+
if from_0_funding_key_0 == from_1_funding_key_0
5322+
|| from_0_funding_key_0 == from_1_funding_key_1
5323+
|| from_0_funding_key_1 == from_1_funding_key_0
5324+
|| from_0_funding_key_1 == from_1_funding_key_1 {
5325+
panic!("Funding pubkeys aren't unique");
5326+
}
5327+
5328+
// Timeout HTLC on A's chain and so it can generate a HTLC-Timeout tx
5329+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
5330+
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![local_txn_1[0].clone()] }, 200);
5331+
check_closed_broadcast!(nodes[0], false);
5332+
check_added_monitors!(nodes[0], 1);
5333+
5334+
let htlc_timeout = {
5335+
let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
5336+
assert_eq!(node_txn[0].input.len(), 1);
5337+
assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
5338+
check_spends!(node_txn[0], local_txn_1[0]);
5339+
node_txn[0].clone()
5340+
};
5341+
5342+
let header_201 = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
5343+
nodes[0].block_notifier.block_connected(&Block { header: header_201, txdata: vec![htlc_timeout.clone()] }, 201);
5344+
connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 201, true, header_201.bitcoin_hash());
5345+
expect_payment_failed!(nodes[0], our_payment_hash, true);
5346+
5347+
// Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor
5348+
let new_keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
5349+
let spend_txn = check_spendable_outputs!(nodes[0], 1, new_keys_manager, 100000);
5350+
assert_eq!(spend_txn.len(), 3);
5351+
assert_eq!(spend_txn[0], spend_txn[1]);
5352+
check_spends!(spend_txn[0], local_txn_1[0]);
5353+
check_spends!(spend_txn[2], htlc_timeout);
5354+
}
5355+
52835356
#[test]
52845357
fn test_static_output_closing_tx() {
52855358
let chanmon_cfgs = create_chanmon_cfgs(2);

0 commit comments

Comments
 (0)