Skip to content

Commit 6e307c6

Browse files
author
Antoine Riard
committed
Add pruning of preimages no longer needed + tests
1 parent d8474c9 commit 6e307c6

File tree

1 file changed

+167
-4
lines changed

1 file changed

+167
-4
lines changed

src/ln/channelmonitor.rs

Lines changed: 167 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,25 @@ impl ChannelMonitor {
286286
}
287287
}
288288
}
289-
// TODO: Prune payment_preimages no longer needed by the revocation (just have to check
290-
// that non-revoked remote commitment tx(n) do not need it, and our latest local commitment
291-
// tx does not need it.
289+
290+
let local_signed_commitment_tx = &self.current_local_signed_commitment_tx;
291+
let remote_claimable_outpoints = &self.remote_claimable_outpoints;
292+
self.payment_preimages.retain(|&k, _| {
293+
for &(ref htlc, _s1, _s2) in &local_signed_commitment_tx.as_ref().expect("Channel needs at least an initial commitment tx !").htlc_outputs {
294+
if k == htlc.payment_hash {
295+
return true
296+
}
297+
}
298+
for (_tx, htlcs) in remote_claimable_outpoints {
299+
for htlc in htlcs {
300+
if k == htlc.payment_hash {
301+
return true
302+
}
303+
}
304+
}
305+
false
306+
});
307+
292308
Ok(())
293309
}
294310

@@ -796,9 +812,15 @@ impl ChannelMonitor {
796812
mod tests {
797813
use bitcoin::util::misc::hex_bytes;
798814
use bitcoin::blockdata::script::Script;
815+
use bitcoin::util::hash::{Hash160,Sha256dHash};
816+
use bitcoin::blockdata::transaction::Transaction;
799817
use ln::channelmonitor::ChannelMonitor;
818+
use ln::channelmonitor::LocalSignedTx;
819+
use ln::chan_utils::HTLCOutputInCommitment;
800820
use secp256k1::key::{SecretKey,PublicKey};
801-
use secp256k1::Secp256k1;
821+
use secp256k1::{Secp256k1, Signature};
822+
use rand::{thread_rng,Rng};
823+
use std::collections::HashMap;
802824

803825
#[test]
804826
fn test_per_commitment_storage() {
@@ -1154,5 +1176,146 @@ mod tests {
11541176
}
11551177
}
11561178

1179+
macro_rules! gen_local_tx {
1180+
($hex : expr, $monitor : expr, $htlcs : expr, $rng : expr, $preimage : expr, $hash : expr) => {
1181+
{
1182+
1183+
let mut htlcs = Vec::new();
1184+
1185+
for _i in 0..$htlcs {
1186+
$rng.fill_bytes(&mut $preimage);
1187+
$hash[0..20].clone_from_slice(&Hash160::from_data(&$preimage)[0..20]);
1188+
$monitor.provide_payment_preimage(&$hash, &$preimage);
1189+
htlcs.push((HTLCOutputInCommitment {
1190+
offered : true,
1191+
amount_msat : 0,
1192+
cltv_expiry : 0,
1193+
payment_hash : $hash.clone(),
1194+
transaction_output_index : 0,
1195+
}, Signature::from_der(&Secp256k1::new(), $hex).unwrap(),
1196+
Signature::from_der(&Secp256k1::new(), $hex).unwrap()))
1197+
}
1198+
1199+
Some(LocalSignedTx {
1200+
txid: Sha256dHash::from_data(&[]),
1201+
tx: Transaction {
1202+
version: 0,
1203+
lock_time: 0,
1204+
input: Vec::new(),
1205+
output: Vec::new(),
1206+
},
1207+
revocation_key: PublicKey::new(),
1208+
a_htlc_key: PublicKey::new(),
1209+
b_htlc_key: PublicKey::new(),
1210+
delayed_payment_key: PublicKey::new(),
1211+
feerate_per_kw: 0,
1212+
htlc_outputs: htlcs,
1213+
})
1214+
}
1215+
}
1216+
}
1217+
1218+
macro_rules! gen_remote_htlcs {
1219+
($monitor : expr, $tx : expr, $htlcs : expr, $rng : expr, $preimage : expr, $hash: expr) => {
1220+
{
1221+
let mut remote_outpoints = HashMap::new();
1222+
1223+
for i in 0..$tx {
1224+
1225+
let tx_zero = Transaction {
1226+
version : 0,
1227+
lock_time : i,
1228+
input : Vec::new(),
1229+
output: Vec::new(),
1230+
};
1231+
1232+
let mut htlcs = Vec::new();
1233+
1234+
for _i in 0..$htlcs {
1235+
$rng.fill_bytes(&mut $preimage);
1236+
$hash[0..20].clone_from_slice(&Hash160::from_data(&$preimage)[0..20]);
1237+
$monitor.provide_payment_preimage(&$hash, &$preimage);
1238+
htlcs.push(HTLCOutputInCommitment {
1239+
offered : true,
1240+
amount_msat : 0,
1241+
cltv_expiry : 0,
1242+
payment_hash : $hash.clone(),
1243+
transaction_output_index : 0,
1244+
});
1245+
}
1246+
remote_outpoints.insert(tx_zero.txid(), htlcs);
1247+
}
1248+
remote_outpoints
1249+
}
1250+
}
1251+
}
1252+
1253+
#[test]
1254+
fn test_prune_preimages() {
1255+
1256+
let mut monitor : ChannelMonitor;
1257+
let secp_ctx = Secp256k1::new();
1258+
let mut preimage : [u8;32] = [0;32];
1259+
let mut hash : [u8;32] = [0;32];
1260+
let mut rng = thread_rng();
1261+
1262+
{
1263+
monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
1264+
1265+
for _i in 0..30 {
1266+
rng.fill_bytes(&mut preimage);
1267+
hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
1268+
monitor.provide_payment_preimage(&hash, &preimage);
1269+
}
1270+
monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 10, rng, preimage, hash);
1271+
monitor.remote_claimable_outpoints = gen_remote_htlcs!(monitor, 1, 10, rng, preimage, hash);
1272+
monitor.provide_secret(0, [0;32], None);
1273+
assert_eq!(monitor.payment_preimages.len(), 20);
1274+
}
1275+
1276+
1277+
{
1278+
monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
1279+
1280+
for _i in 0..30 {
1281+
rng.fill_bytes(&mut preimage);
1282+
hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
1283+
monitor.provide_payment_preimage(&hash, &preimage);
1284+
}
1285+
monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 0, rng, preimage, hash);
1286+
monitor.remote_claimable_outpoints = gen_remote_htlcs!(monitor, 0, 0, rng, preimage, hash);
1287+
monitor.provide_secret(0, [0;32], None);
1288+
assert_eq!(monitor.payment_preimages.len(), 0);
1289+
}
1290+
1291+
{
1292+
monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
1293+
1294+
for _i in 0..30 {
1295+
rng.fill_bytes(&mut preimage);
1296+
hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
1297+
monitor.provide_payment_preimage(&hash, &preimage);
1298+
}
1299+
monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 0, rng, preimage, hash);
1300+
monitor.remote_claimable_outpoints = gen_remote_htlcs!(monitor, 5, 5, rng, preimage, hash);
1301+
monitor.provide_secret(0, [0;32], None);
1302+
assert_eq!(monitor.payment_preimages.len(), 25);
1303+
}
1304+
1305+
{
1306+
monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
1307+
1308+
for _i in 0..30 {
1309+
rng.fill_bytes(&mut preimage);
1310+
hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
1311+
monitor.provide_payment_preimage(&hash, &preimage);
1312+
}
1313+
monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 25, rng, preimage, hash);
1314+
monitor.remote_claimable_outpoints = gen_remote_htlcs!(monitor, 0, 0, rng, preimage, hash);
1315+
monitor.provide_secret(0, [0;32], None);
1316+
assert_eq!(monitor.payment_preimages.len(), 25);
1317+
}
1318+
}
1319+
11571320
// Further testing is done in the ChannelManager integration tests.
11581321
}

0 commit comments

Comments
 (0)