Skip to content

Commit 6903094

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

File tree

1 file changed

+167
-5
lines changed

1 file changed

+167
-5
lines changed

src/ln/channelmonitor.rs

Lines changed: 167 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,27 @@ 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 mut pruned_payment_preimages = HashMap::with_capacity(self.payment_preimages.capacity());
291+
for (k, v) in self.payment_preimages.drain() {
292+
for (htlc, _s1, _s2) in &self.current_local_signed_commitment_tx.as_ref().expect("Channel need at least an initial commitment tx !").htlc_outputs {
293+
if k == htlc.payment_hash {
294+
pruned_payment_preimages.insert(k, v);
295+
}
296+
}
297+
for (_tx, htlcs) in &self.remote_claimable_outpoints {
298+
for htlc in htlcs {
299+
if k == htlc.payment_hash {
300+
pruned_payment_preimages.insert(k, v);
301+
}
302+
}
303+
}
304+
}
305+
self.payment_preimages = pruned_payment_preimages;
306+
292307
Ok(())
293308
}
294-
309+
295310
/// Informs this monitor of the latest remote (ie non-broadcastable) commitment transaction.
296311
/// The monitor watches for it to be broadcasted and then uses the HTLC information (and
297312
/// possibly future revocation/preimage information) to claim outputs where possible.
@@ -796,9 +811,15 @@ impl ChannelMonitor {
796811
mod tests {
797812
use bitcoin::util::misc::hex_bytes;
798813
use bitcoin::blockdata::script::Script;
814+
use bitcoin::util::hash::{Hash160,Sha256dHash};
815+
use bitcoin::blockdata::transaction::Transaction;
799816
use ln::channelmonitor::ChannelMonitor;
817+
use ln::channelmonitor::LocalSignedTx;
818+
use ln::chan_utils::HTLCOutputInCommitment;
800819
use secp256k1::key::{SecretKey,PublicKey};
801-
use secp256k1::Secp256k1;
820+
use secp256k1::{Secp256k1, Signature};
821+
use rand::{thread_rng,Rng};
822+
use std::collections::HashMap;
802823

803824
#[test]
804825
fn test_per_commitment_storage() {
@@ -1154,5 +1175,146 @@ mod tests {
11541175
}
11551176
}
11561177

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

0 commit comments

Comments
 (0)