/// Attempts to claim a remote HTLC-Success/HTLC-Timeout's outputs using the revocation key
fn check_spend_remote_htlc(&mut self, tx: &Transaction, commitment_number: u64, height: u32, fee_estimator: &FeeEstimator) -> (Option<Transaction>, Option<SpendableOutputDescriptor>) {
+ //TODO: send back new outputs to guarantee pending_claim_request consistency
if tx.input.len() != 1 || tx.output.len() != 1 {
return (None, None)
}
}
fn block_connected(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &Sha256dHash, broadcaster: &BroadcasterInterface, fee_estimator: &FeeEstimator)-> (Vec<(Sha256dHash, Vec<TxOut>)>, Vec<SpendableOutputDescriptor>, Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)>) {
+ log_trace!(self, "Block {} at height {} connected with {} txn matched", block_hash, height, txn_matched.len());
let mut watch_outputs = Vec::new();
let mut spendable_outputs = Vec::new();
let mut htlc_updated = Vec::new();
}
// Scan all input to verify is one of the outpoint spent is of interest for us
- let mut claimed_outpoints = Vec::new();
- let mut claimed_input_material = Vec::new();
+ let mut claimed_outputs_material = Vec::new();
for inp in &tx.input {
if let Some(ancestor_claimable_txid) = self.claimable_outpoints.get(&inp.previous_output) {
// If outpoint has claim request pending on it...
//... we need to verify equality between transaction outpoints and claim request
// outpoints to know if transaction is the original claim or a bumped one issued
// by us.
- for claim_inp in claim_material.per_input_material.keys() {
- if *claim_inp == inp.previous_output {
- claimed_outpoints.push(inp.previous_output.clone());
+ let mut set_equality = true;
+ if claim_material.per_input_material.len() != tx.input.len() {
+ set_equality = false;
+ } else {
+ for (claim_inp, tx_inp) in claim_material.per_input_material.keys().zip(tx.input.iter()) {
+ if *claim_inp != tx_inp.previous_output {
+ set_equality = false;
+ }
}
}
- if claimed_outpoints.len() == 0 && claim_material.per_input_material.len() == tx.input.len() { // If true, register claim request to be removed after reaching a block security height
+
+ // If this is our transaction (or our counterparty spent all the outputs
+ // before we could anyway), wait for ANTI_REORG_DELAY and clean the RBF
+ // tracking map.
+ if set_equality {
+ let new_event = OnchainEvent::Claim { claim_request: ancestor_claimable_txid.0.clone() };
match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {
- hash_map::Entry::Occupied(_) => {},
+ hash_map::Entry::Occupied(mut entry) => {
+ if !entry.get().contains(&new_event) {
+ entry.get_mut().push(new_event);
+ }
+ },
hash_map::Entry::Vacant(entry) => {
- entry.insert(vec![OnchainEvent::Claim { claim_request: ancestor_claimable_txid.0.clone()}]);
+ entry.insert(vec![new_event]);
}
}
} else { // If false, generate new claim request with update outpoint set
- for already_claimed in claimed_outpoints.iter() {
- if let Some(input_material) = claim_material.per_input_material.remove(&already_claimed) {
- claimed_input_material.push(input_material);
+ for input in tx.input.iter() {
+ if let Some(input_material) = claim_material.per_input_material.remove(&input.previous_output) {
+ claimed_outputs_material.push((input.previous_output, input_material));
}
}
- // Avoid bump engine using inaccurate feerate due to new transaction size
- claim_material.feerate_previous = 0;
//TODO: recompute soonest_timelock to avoid wasting a bit on fees
bump_candidates.push((ancestor_claimable_txid.0.clone(), claim_material.clone()));
}
}
}
}
- for (outpoint, input_material) in claimed_outpoints.iter().zip(claimed_input_material.drain(..)) {
+ for (outpoint, input_material) in claimed_outputs_material.drain(..) {
+ let new_event = OnchainEvent::ContentiousOutpoint { outpoint, input_material };
match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {
- hash_map::Entry::Occupied(_) => {},
+ hash_map::Entry::Occupied(mut entry) => {
+ if !entry.get().contains(&new_event) {
+ entry.get_mut().push(new_event);
+ }
+ },
hash_map::Entry::Vacant(entry) => {
- entry.insert(vec![OnchainEvent::ContentiousOutpoint { outpoint: *outpoint, input_material: input_material }]);
+ entry.insert(vec![new_event]);
}
}
}
OnchainEvent::ContentiousOutpoint { outpoint, input_material } => {
if let Some(ancestor_claimable_txid) = self.claimable_outpoints.get(&outpoint) {
if let Some(claim_material) = self.pending_claim_requests.get_mut(&ancestor_claimable_txid.0) {
- // Avoid bump engine using inaccurate feerate due to new transaction size
- claim_material.feerate_previous = 0;
claim_material.per_input_material.insert(outpoint, input_material);
// Using a HashMap guarantee us than if we have multiple outpoints getting
// resurrected only one bump claim tx is going to be broadcast