Skip to content

Commit d5e25e5

Browse files
committed
Use BumpTransactionEventHandler in tests
1 parent b775aec commit d5e25e5

File tree

3 files changed

+120
-58
lines changed

3 files changed

+120
-58
lines changed

lightning/src/ln/functional_test_utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> {
367367
pub blocks: Arc<Mutex<Vec<(Block, u32)>>>,
368368
pub connect_style: Rc<RefCell<ConnectStyle>>,
369369
pub override_init_features: Rc<RefCell<Option<InitFeatures>>>,
370+
#[cfg(anchors)]
371+
pub wallet_utxo_source: test_utils::TestWalletUtxoSource,
370372
}
371373
impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
372374
pub fn best_block_hash(&self) -> BlockHash {
@@ -2525,6 +2527,8 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
25252527
blocks: Arc::clone(&cfgs[i].tx_broadcaster.blocks),
25262528
connect_style: Rc::clone(&connect_style),
25272529
override_init_features: Rc::clone(&cfgs[i].override_init_features),
2530+
#[cfg(anchors)]
2531+
wallet_utxo_source: test_utils::TestWalletUtxoSource::new(),
25282532
})
25292533
}
25302534

lightning/src/ln/monitor_tests.rs

Lines changed: 39 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::chain::channelmonitor::{ANTI_REORG_DELAY, Balance};
1717
use crate::chain::transaction::OutPoint;
1818
use crate::chain::chaininterface::LowerBoundedFeeEstimator;
1919
#[cfg(anchors)]
20-
use crate::events::bump_transaction::BumpTransactionEvent;
20+
use crate::events::bump_transaction::{BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource};
2121
use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
2222
use crate::ln::channel;
2323
#[cfg(anchors)]
@@ -1938,7 +1938,6 @@ fn test_yield_anchors_events() {
19381938
// allowing the consumer to provide additional fees to the commitment transaction to be
19391939
// broadcast. Once the commitment transaction confirms, events for the HTLC resolution should be
19401940
// emitted by LDK, such that the consumer can attach fees to the zero fee HTLC transactions.
1941-
let secp = Secp256k1::new();
19421941
let mut chanmon_cfgs = create_chanmon_cfgs(2);
19431942
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
19441943
let mut anchors_config = UserConfig::default();
@@ -1955,6 +1954,8 @@ fn test_yield_anchors_events() {
19551954

19561955
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
19571956

1957+
*nodes[0].fee_estimator.sat_per_kw.lock().unwrap() *= 2;
1958+
19581959
connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1);
19591960
check_closed_broadcast!(&nodes[0], true);
19601961
assert!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
@@ -1964,34 +1965,38 @@ fn test_yield_anchors_events() {
19641965
&LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger
19651966
);
19661967

1968+
let coinbase_tx = Transaction {
1969+
version: 2,
1970+
lock_time: PackedLockTime::ZERO,
1971+
input: vec![TxIn { ..Default::default() }],
1972+
output: vec![TxOut { // UTXO to attach fees to `anchor_tx` and `htlc_txs`
1973+
value: Amount::ONE_BTC.to_sat(),
1974+
script_pubkey: nodes[0].wallet_utxo_source.change_script().unwrap(),
1975+
}],
1976+
};
1977+
nodes[0].wallet_utxo_source.add_utxo(
1978+
bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, coinbase_tx.output[0].value,
1979+
);
1980+
nodes[0].wallet_utxo_source.add_utxo(
1981+
bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 1 }, coinbase_tx.output[0].value * 2,
1982+
);
1983+
let wallet = Wallet::new(&nodes[0].wallet_utxo_source);
1984+
let bump_event_handler = BumpTransactionEventHandler::new(
1985+
nodes[0].tx_broadcaster, &wallet, nodes[0].keys_manager, nodes[0].logger,
1986+
);
1987+
19671988
let mut holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
19681989
assert_eq!(holder_events.len(), 1);
1969-
let (commitment_tx, anchor_tx) = match holder_events.pop().unwrap() {
1970-
Event::BumpTransaction(BumpTransactionEvent::ChannelClose { commitment_tx, anchor_descriptor, .. }) => {
1971-
assert_eq!(commitment_tx.input.len(), 1);
1972-
assert_eq!(commitment_tx.output.len(), 6);
1973-
let mut anchor_tx = Transaction {
1974-
version: 2,
1975-
lock_time: PackedLockTime::ZERO,
1976-
input: vec![
1977-
TxIn { previous_output: anchor_descriptor.outpoint, ..Default::default() },
1978-
TxIn { ..Default::default() },
1979-
],
1980-
output: vec![TxOut {
1981-
value: Amount::ONE_BTC.to_sat(),
1982-
script_pubkey: Script::new_op_return(&[]),
1983-
}],
1984-
};
1985-
let signer = nodes[0].keys_manager.derive_channel_keys(
1986-
anchor_descriptor.channel_value_satoshis, &anchor_descriptor.channel_keys_id,
1987-
);
1988-
let funding_sig = signer.sign_holder_anchor_input(&mut anchor_tx, 0, &secp).unwrap();
1989-
anchor_tx.input[0].witness = chan_utils::build_anchor_input_witness(
1990-
&signer.pubkeys().funding_pubkey, &funding_sig
1991-
);
1992-
(commitment_tx, anchor_tx)
1993-
},
1994-
_ => panic!("Unexpected event"),
1990+
let (commitment_tx, anchor_tx) = {
1991+
bump_event_handler.handle_event(holder_events.pop().unwrap());
1992+
let mut txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
1993+
assert_eq!(txn.len(), 2);
1994+
let anchor_tx = txn.pop().unwrap();
1995+
let commitment_tx = txn.pop().unwrap();
1996+
assert_eq!(commitment_tx.input.len(), 1);
1997+
assert_eq!(commitment_tx.output.len(), 6);
1998+
check_spends!(anchor_tx, commitment_tx, coinbase_tx);
1999+
(commitment_tx, anchor_tx)
19952000
};
19962001

19972002
mine_transactions(&nodes[0], &[&commitment_tx, &anchor_tx]);
@@ -2011,36 +2016,12 @@ fn test_yield_anchors_events() {
20112016
};
20122017
let mut htlc_txs = Vec::with_capacity(2);
20132018
for event in holder_events {
2014-
match event {
2015-
Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { htlc_descriptors, tx_lock_time, .. }) => {
2016-
assert_eq!(htlc_descriptors.len(), 1);
2017-
let htlc_descriptor = &htlc_descriptors[0];
2018-
let signer = nodes[0].keys_manager.derive_channel_keys(
2019-
htlc_descriptor.channel_value_satoshis, &htlc_descriptor.channel_keys_id
2020-
);
2021-
let per_commitment_point = signer.get_per_commitment_point(htlc_descriptor.per_commitment_number, &secp);
2022-
let mut htlc_tx = Transaction {
2023-
version: 2,
2024-
lock_time: tx_lock_time,
2025-
input: vec![
2026-
htlc_descriptor.unsigned_tx_input(), // HTLC input
2027-
TxIn { ..Default::default() } // Fee input
2028-
],
2029-
output: vec![
2030-
htlc_descriptor.tx_output(&per_commitment_point, &secp), // HTLC output
2031-
TxOut { // Fee input change
2032-
value: Amount::ONE_BTC.to_sat(),
2033-
script_pubkey: Script::new_op_return(&[]),
2034-
}
2035-
]
2036-
};
2037-
let our_sig = signer.sign_holder_htlc_transaction(&mut htlc_tx, 0, htlc_descriptor, &secp).unwrap();
2038-
let witness_script = htlc_descriptor.witness_script(&per_commitment_point, &secp);
2039-
htlc_tx.input[0].witness = htlc_descriptor.tx_input_witness(&our_sig, &witness_script);
2040-
htlc_txs.push(htlc_tx);
2041-
},
2042-
_ => panic!("Unexpected event"),
2043-
}
2019+
// Ideally we'd use the change UTXO from `anchor_tx` here to not reuse the same UTXO but it
2020+
// doesn't really matter since we're not validating against an actual chain backend anyway.
2021+
bump_event_handler.handle_event(event);
2022+
let mut txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
2023+
assert_eq!(txn.len(), 1);
2024+
htlc_txs.push(txn.pop().unwrap());
20442025
}
20452026

20462027
mine_transactions(&nodes[0], &[&htlc_txs[0], &htlc_txs[1]]);

lightning/src/util/test_utils.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ use crate::util::config::UserConfig;
3131
use crate::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
3232
use crate::util::logger::{Logger, Level, Record};
3333
use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable};
34+
#[cfg(anchors)]
35+
use bitcoin::Witness;
36+
#[cfg(anchors)]
37+
use bitcoin::blockdata::transaction::EcdsaSighashType;
38+
#[cfg(anchors)]
39+
use bitcoin::util::sighash::SighashCache;
40+
#[cfg(anchors)]
41+
use crate::events::bump_transaction::{Utxo, WalletSource};
42+
#[cfg(anchors)]
43+
use crate::util::crypto::sign;
3444

3545
use bitcoin::blockdata::constants::genesis_block;
3646
use bitcoin::blockdata::transaction::{Transaction, TxOut};
@@ -1007,3 +1017,70 @@ impl Drop for TestScorer {
10071017
}
10081018
}
10091019
}
1020+
1021+
#[cfg(anchors)]
1022+
pub struct TestWalletUtxoSource {
1023+
secp: Secp256k1<bitcoin::secp256k1::All>,
1024+
utxos: RefCell<Vec<Utxo>>,
1025+
}
1026+
1027+
#[cfg(anchors)]
1028+
impl TestWalletUtxoSource {
1029+
pub fn new() -> Self {
1030+
Self {
1031+
secp: Secp256k1::new(),
1032+
utxos: RefCell::new(Vec::new()),
1033+
}
1034+
}
1035+
1036+
pub fn add_utxo(&self, outpoint: bitcoin::OutPoint, value: u64) {
1037+
let secret_key = SecretKey::from_slice(&[1; 32]).unwrap();
1038+
let public_key = bitcoin::PublicKey::new(secret_key.public_key(&self.secp));
1039+
let script_pubkey = Script::new_v0_p2wpkh(&public_key.wpubkey_hash().unwrap());
1040+
self.utxos.borrow_mut().push(Utxo {
1041+
outpoint,
1042+
output: TxOut {
1043+
value,
1044+
script_pubkey,
1045+
},
1046+
witness_weight: 1 /* num stack items */ + 1 /* sig push */ + 73 /* sig */ + 1 /* pubkey push */ + 33 /* pubkey */,
1047+
})
1048+
}
1049+
}
1050+
1051+
#[cfg(anchors)]
1052+
impl WalletSource for TestWalletUtxoSource {
1053+
fn list_confirmed_utxos(&self) -> Result<Vec<Utxo>, ()> {
1054+
Ok(self.utxos.borrow().clone())
1055+
}
1056+
fn change_script(&self) -> Result<Script, ()> {
1057+
let secret_key = SecretKey::from_slice(&[1; 32]).unwrap();
1058+
let public_key = bitcoin::PublicKey::new(secret_key.public_key(&self.secp));
1059+
Ok(Script::new_v0_p2wpkh(&public_key.wpubkey_hash().unwrap()))
1060+
}
1061+
fn sign_tx(&self, tx: &mut Transaction) -> Result<(), ()> {
1062+
let utxos = self.utxos.borrow();
1063+
let mut witnesses = Vec::new();
1064+
for (idx, input) in tx.input.iter().enumerate() {
1065+
let utxo = utxos.iter().find(|utxo| input.previous_output == utxo.outpoint);
1066+
if utxo.is_none() {
1067+
continue;
1068+
}
1069+
let utxo = utxo.unwrap();
1070+
let secret_key = SecretKey::from_slice(&[1; 32]).unwrap();
1071+
let public_key = bitcoin::PublicKey::new(secret_key.public_key(&self.secp));
1072+
let witness_script = Script::new_p2pkh(&public_key.pubkey_hash());
1073+
let sighash = hash_to_message!(&SighashCache::new(&*tx).segwit_signature_hash(
1074+
idx, &witness_script, utxo.output.value, EcdsaSighashType::All
1075+
).unwrap()[..]);
1076+
let sig = sign(&self.secp, &sighash, &secret_key);
1077+
let mut sig = sig.serialize_der().to_vec();
1078+
sig.push(EcdsaSighashType::All as u8);
1079+
witnesses.push((idx, Witness::from_vec(vec![sig, public_key.to_bytes()])));
1080+
}
1081+
for (idx, witness) in witnesses {
1082+
tx.input[idx].witness = witness;
1083+
}
1084+
Ok(())
1085+
}
1086+
}

0 commit comments

Comments
 (0)