Skip to content

Commit ef7b9fd

Browse files
author
Antoine Riard
committed
Add unit test for get_witnesses_weight
1 parent 32e2b7a commit ef7b9fd

File tree

1 file changed

+122
-3
lines changed

1 file changed

+122
-3
lines changed

src/ln/channelmonitor.rs

Lines changed: 122 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ struct LocalSignedTx {
342342
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<(Signature, Signature)>, Option<HTLCSource>)>,
343343
}
344344

345+
#[derive(PartialEq)]
345346
enum InputDescriptors {
346347
RevokedOfferedHTLC,
347348
RevokedReceivedHTLC,
@@ -2274,13 +2275,19 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
22742275

22752276
#[cfg(test)]
22762277
mod tests {
2277-
use bitcoin::blockdata::script::Script;
2278-
use bitcoin::blockdata::transaction::Transaction;
2278+
use bitcoin::blockdata::script::{Script, Builder};
2279+
use bitcoin::blockdata::opcodes;
2280+
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType};
2281+
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
2282+
use bitcoin::util::bip143;
22792283
use bitcoin_hashes::Hash;
22802284
use bitcoin_hashes::sha256::Hash as Sha256;
2285+
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
2286+
use bitcoin_hashes::hex::FromHex;
22812287
use hex;
22822288
use ln::channelmanager::{PaymentPreimage, PaymentHash};
2283-
use ln::channelmonitor::ChannelMonitor;
2289+
use ln::channelmonitor::{ChannelMonitor, InputDescriptors};
2290+
use ln::chan_utils;
22842291
use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys};
22852292
use util::test_utils::TestLogger;
22862293
use secp256k1::key::{SecretKey,PublicKey};
@@ -2757,5 +2764,117 @@ mod tests {
27572764
test_preimages_exist!(&preimages[0..5], monitor);
27582765
}
27592766

2767+
#[test]
2768+
fn test_claim_txn_weight_computation() {
2769+
// We test Claim txn weight, knowing that we want expected weigth and
2770+
// not actual case to avoid sigs and time-lock delays hell variances.
2771+
2772+
let secp_ctx = Secp256k1::new();
2773+
let privkey = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
2774+
let pubkey = PublicKey::from_secret_key(&secp_ctx, &privkey);
2775+
let mut sum_actual_sigs: u64 = 0;
2776+
2777+
macro_rules! sign_input {
2778+
($sighash_parts: expr, $input: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
2779+
let htlc = HTLCOutputInCommitment {
2780+
offered: if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::OfferedHTLC { true } else { false },
2781+
amount_msat: 0,
2782+
cltv_expiry: 2 << 16,
2783+
payment_hash: PaymentHash([1; 32]),
2784+
transaction_output_index: Some($idx),
2785+
};
2786+
let redeem_script = if *$input_type == InputDescriptors::RevokedOutput { chan_utils::get_revokeable_redeemscript(&pubkey, 256, &pubkey) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &pubkey, &pubkey, &pubkey) };
2787+
let sighash = hash_to_message!(&$sighash_parts.sighash_all(&$input, &redeem_script, $amount)[..]);
2788+
let sig = secp_ctx.sign(&sighash, &privkey);
2789+
$input.witness.push(sig.serialize_der().to_vec());
2790+
$input.witness[0].push(SigHashType::All as u8);
2791+
sum_actual_sigs += $input.witness[0].len() as u64;
2792+
if *$input_type == InputDescriptors::RevokedOutput {
2793+
$input.witness.push(vec!(1));
2794+
} else if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::RevokedReceivedHTLC {
2795+
$input.witness.push(pubkey.clone().serialize().to_vec());
2796+
} else if *$input_type == InputDescriptors::ReceivedHTLC {
2797+
$input.witness.push(vec![0]);
2798+
} else {
2799+
$input.witness.push(PaymentPreimage([1; 32]).0.to_vec());
2800+
}
2801+
$input.witness.push(redeem_script.into_bytes());
2802+
println!("witness[0] {}", $input.witness[0].len());
2803+
println!("witness[1] {}", $input.witness[1].len());
2804+
println!("witness[2] {}", $input.witness[2].len());
2805+
}
2806+
}
2807+
2808+
let script_pubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script();
2809+
let txid = Sha256dHash::from_hex("56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d").unwrap();
2810+
2811+
// Justice tx with 1 to_local, 2 revoked offered HTLCs, 1 revoked received HTLCs
2812+
let mut claim_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
2813+
for i in 0..4 {
2814+
claim_tx.input.push(TxIn {
2815+
previous_output: BitcoinOutPoint {
2816+
txid,
2817+
vout: i,
2818+
},
2819+
script_sig: Script::new(),
2820+
sequence: 0xfffffffd,
2821+
witness: Vec::new(),
2822+
});
2823+
}
2824+
claim_tx.output.push(TxOut {
2825+
script_pubkey: script_pubkey.clone(),
2826+
value: 0,
2827+
});
2828+
let base_weight = claim_tx.get_weight() + 2; // segwit flag, not added because lack of witness input at this step
2829+
let sighash_parts = bip143::SighashComponents::new(&claim_tx);
2830+
let inputs_des = vec![InputDescriptors::RevokedOutput, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedReceivedHTLC];
2831+
for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
2832+
sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
2833+
}
2834+
assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des), claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
2835+
2836+
// Claim tx with 1 offered HTLCs, 3 received HTLCs
2837+
claim_tx.input.clear();
2838+
sum_actual_sigs = 0;
2839+
for i in 0..4 {
2840+
claim_tx.input.push(TxIn {
2841+
previous_output: BitcoinOutPoint {
2842+
txid,
2843+
vout: i,
2844+
},
2845+
script_sig: Script::new(),
2846+
sequence: 0xfffffffd,
2847+
witness: Vec::new(),
2848+
});
2849+
}
2850+
let base_weight = claim_tx.get_weight() + 2;
2851+
let sighash_parts = bip143::SighashComponents::new(&claim_tx);
2852+
let inputs_des = vec![InputDescriptors::OfferedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC];
2853+
for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
2854+
sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
2855+
}
2856+
assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des), claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
2857+
2858+
// Justice tx with 1 revoked HTLC-Success tx output
2859+
claim_tx.input.clear();
2860+
sum_actual_sigs = 0;
2861+
claim_tx.input.push(TxIn {
2862+
previous_output: BitcoinOutPoint {
2863+
txid,
2864+
vout: 0,
2865+
},
2866+
script_sig: Script::new(),
2867+
sequence: 0xfffffffd,
2868+
witness: Vec::new(),
2869+
});
2870+
let base_weight = claim_tx.get_weight() + 2;
2871+
let sighash_parts = bip143::SighashComponents::new(&claim_tx);
2872+
let inputs_des = vec![InputDescriptors::RevokedOutput];
2873+
for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
2874+
sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
2875+
}
2876+
assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des), claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
2877+
}
2878+
27602879
// Further testing is done in the ChannelManager integration tests.
27612880
}

0 commit comments

Comments
 (0)