+
+ macro_rules! gen_local_tx {
+ ($hex : expr, $monitor : expr, $htlcs : expr, $rng : expr, $preimage : expr, $hash : expr) => {
+ {
+
+ let mut htlcs = Vec::new();
+
+ for _i in 0..$htlcs {
+ $rng.fill_bytes(&mut $preimage);
+ $hash[0..20].clone_from_slice(&Hash160::from_data(&$preimage)[0..20]);
+ $monitor.provide_payment_preimage(&$hash, &$preimage);
+ htlcs.push((HTLCOutputInCommitment {
+ offered : true,
+ amount_msat : 0,
+ cltv_expiry : 0,
+ payment_hash : $hash.clone(),
+ transaction_output_index : 0,
+ }, Signature::from_der(&Secp256k1::new(), $hex).unwrap(),
+ Signature::from_der(&Secp256k1::new(), $hex).unwrap()))
+ }
+
+ Some(LocalSignedTx {
+ txid: Sha256dHash::from_data(&[]),
+ tx: Transaction {
+ version: 0,
+ lock_time: 0,
+ input: Vec::new(),
+ output: Vec::new(),
+ },
+ revocation_key: PublicKey::new(),
+ a_htlc_key: PublicKey::new(),
+ b_htlc_key: PublicKey::new(),
+ delayed_payment_key: PublicKey::new(),
+ feerate_per_kw: 0,
+ htlc_outputs: htlcs,
+ })
+ }
+ }
+ }
+
+ macro_rules! gen_remote_outpoints {
+ ($monitor : expr, $tx : expr, $htlcs : expr, $rng : expr, $preimage : expr, $hash: expr, $number : expr) => {
+ {
+ let mut commitment_number = $number;
+
+ for i in 0..$tx {
+
+ let tx_zero = Transaction {
+ version : 0,
+ lock_time : i,
+ input : Vec::new(),
+ output: Vec::new(),
+ };
+
+ let mut htlcs = Vec::new();
+
+ for _i in 0..$htlcs {
+ $rng.fill_bytes(&mut $preimage);
+ $hash[0..20].clone_from_slice(&Hash160::from_data(&$preimage)[0..20]);
+ $monitor.provide_payment_preimage(&$hash, &$preimage);
+ htlcs.push(HTLCOutputInCommitment {
+ offered : true,
+ amount_msat : 0,
+ cltv_expiry : 0,
+ payment_hash : $hash.clone(),
+ transaction_output_index : 0,
+ });
+ }
+ commitment_number -= 1;
+ $monitor.provide_latest_remote_commitment_tx_info(&tx_zero, htlcs, commitment_number);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_prune_preimages() {
+
+ let mut monitor: ChannelMonitor;
+ let mut secrets: Vec<[u8; 32]> = Vec::new();
+ let secp_ctx = Secp256k1::new();
+ let mut preimage: [u8;32] = [0;32];
+ let mut hash: [u8;32] = [0;32];
+ let mut rng = thread_rng();
+
+ {
+ // insert 30 random hash, 10 from local, 10 from remote, prune 30/50
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
+
+ for _i in 0..30 {
+ rng.fill_bytes(&mut preimage);
+ hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
+ monitor.provide_payment_preimage(&hash, &preimage);
+ }
+ monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 10, rng, preimage, hash);
+ gen_remote_outpoints!(monitor, 1, 10, rng, preimage, hash, 281474976710654);
+ secrets.clear();
+ secrets.push([0; 32]);
+ secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+ monitor.provide_secret(281474976710655, secrets.last().unwrap().clone(), None);
+ assert_eq!(monitor.payment_preimages.len(), 20);
+ }
+
+
+ {
+ // insert 30 random hash, prune 30/30
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
+
+ for _i in 0..30 {
+ rng.fill_bytes(&mut preimage);
+ hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
+ monitor.provide_payment_preimage(&hash, &preimage);
+ }
+ monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 0, rng, preimage, hash);
+ gen_remote_outpoints!(monitor, 0, 0, rng, preimage, hash, 281474976710655);
+ secrets.clear();
+ secrets.push([0; 32]);
+ secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+ monitor.provide_secret(281474976710655, secrets.last().unwrap().clone(), None);
+ assert_eq!(monitor.payment_preimages.len(), 0);
+ }
+
+ {
+ // insert 30 random hash, 25 on 5 remotes, prune 30/55
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
+
+ for _i in 0..30 {
+ rng.fill_bytes(&mut preimage);
+ hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
+ monitor.provide_payment_preimage(&hash, &preimage);
+ }
+ monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 0, rng, preimage, hash);
+ gen_remote_outpoints!(monitor, 5, 5, rng, preimage, hash, 281474976710654);
+ secrets.clear();
+ secrets.push([0; 32]);
+ secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+ monitor.provide_secret(281474976710655, secrets.last().unwrap().clone(), None);
+ assert_eq!(monitor.payment_preimages.len(), 25);
+ }
+
+ {
+ // insert 30 random hash, 25 from local, prune 30/55
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), 0, Script::new());
+
+ for _i in 0..30 {
+ rng.fill_bytes(&mut preimage);
+ hash[0..20].clone_from_slice(&Hash160::from_data(&preimage)[0..20]);
+ monitor.provide_payment_preimage(&hash, &preimage);
+ }
+ monitor.current_local_signed_commitment_tx = gen_local_tx!(&hex_bytes("3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd").unwrap()[..], monitor, 25, rng, preimage, hash);
+ gen_remote_outpoints!(monitor, 0, 0, rng, preimage, hash, 281474976710655);
+ secrets.clear();
+ secrets.push([0; 32]);
+ secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+ monitor.provide_secret(281474976710655, secrets.last().unwrap().clone(), None);
+ assert_eq!(monitor.payment_preimages.len(), 25);
+ }
+ }
+
+ // Further testing is done in the ChannelManager integration tests.