X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fonchaintx.rs;h=05d59431fc3a815585554eae7ffd5323d72b4112;hb=a0917e50e88d849302ec2651c4255789ad5c940c;hp=2871abbc22312d5f9e4f31aa5b9ec4fd49ddbf9d;hpb=88ce7d6575dd376e98e680d0c0813c7b79151773;p=rust-lightning diff --git a/lightning/src/chain/onchaintx.rs b/lightning/src/chain/onchaintx.rs index 2871abbc..05d59431 100644 --- a/lightning/src/chain/onchaintx.rs +++ b/lightning/src/chain/onchaintx.rs @@ -374,13 +374,13 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP signer.provide_channel_parameters(&channel_parameters); let pending_claim_requests_len: u64 = Readable::read(reader)?; - let mut pending_claim_requests = HashMap::with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); + let mut pending_claim_requests = hash_map_with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..pending_claim_requests_len { pending_claim_requests.insert(Readable::read(reader)?, Readable::read(reader)?); } let claimable_outpoints_len: u64 = Readable::read(reader)?; - let mut claimable_outpoints = HashMap::with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); + let mut claimable_outpoints = hash_map_with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..claimable_outpoints_len { let outpoint = Readable::read(reader)?; let ancestor_claim_txid = Readable::read(reader)?; @@ -445,8 +445,8 @@ impl OnchainTxHandler prev_holder_commitment: None, signer, channel_transaction_parameters: channel_parameters, - pending_claim_requests: HashMap::new(), - claimable_outpoints: HashMap::new(), + pending_claim_requests: new_hash_map(), + claimable_outpoints: new_hash_map(), locktimed_packages: BTreeMap::new(), onchain_events_awaiting_threshold_conf: Vec::new(), pending_claim_events: Vec::new(), @@ -473,14 +473,13 @@ impl OnchainTxHandler /// feerate changes between blocks, and ensuring reliability if broadcasting fails. We recommend /// invoking this every 30 seconds, or lower if running in an environment with spotty /// connections, like on mobile. - pub(crate) fn rebroadcast_pending_claims( + pub(super) fn rebroadcast_pending_claims( &mut self, current_height: u32, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, - L::Target: Logger, { let mut bump_requests = Vec::with_capacity(self.pending_claim_requests.len()); for (claim_id, request) in self.pending_claim_requests.iter() { @@ -528,13 +527,11 @@ impl OnchainTxHandler /// /// Panics if there are signing errors, because signing operations in reaction to on-chain /// events are not expected to fail, and if they do, we may lose funds. - fn generate_claim( + fn generate_claim( &mut self, cur_height: u32, cached_request: &PackageTemplate, force_feerate_bump: bool, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Option<(u32, u64, OnchainClaim)> - where - F::Target: FeeEstimator, - L::Target: Logger, + where F::Target: FeeEstimator, { let request_outpoints = cached_request.outpoints(); if request_outpoints.is_empty() { @@ -679,6 +676,25 @@ impl OnchainTxHandler None } + pub fn abandon_claim(&mut self, outpoint: &BitcoinOutPoint) { + let claim_id = self.claimable_outpoints.get(outpoint).map(|(claim_id, _)| *claim_id) + .or_else(|| { + self.pending_claim_requests.iter() + .find(|(_, claim)| claim.outpoints().iter().any(|claim_outpoint| *claim_outpoint == outpoint)) + .map(|(claim_id, _)| *claim_id) + }); + if let Some(claim_id) = claim_id { + if let Some(claim) = self.pending_claim_requests.remove(&claim_id) { + for outpoint in claim.outpoints() { + self.claimable_outpoints.remove(outpoint); + } + } + } else { + self.locktimed_packages.values_mut().for_each(|claims| + claims.retain(|claim| !claim.outpoints().iter().any(|claim_outpoint| *claim_outpoint == outpoint))); + } + } + /// Upon channelmonitor.block_connected(..) or upon provision of a preimage on the forward link /// for this channel, provide new relevant on-chain transactions and/or new claim requests. /// Together with `update_claims_view_from_matched_txn` this used to be named @@ -688,13 +704,12 @@ impl OnchainTxHandler /// `conf_height` represents the height at which the request was generated. This /// does not need to equal the current blockchain tip height, which should be provided via /// `cur_height`, however it must never be higher than `cur_height`. - pub(crate) fn update_claims_view_from_requests( + pub(super) fn update_claims_view_from_requests( &mut self, requests: Vec, conf_height: u32, cur_height: u32, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, - L::Target: Logger, { log_debug!(logger, "Updating claims view at height {} with {} claim requests", cur_height, requests.len()); let mut preprocessed_requests = Vec::with_capacity(requests.len()); @@ -791,7 +806,9 @@ impl OnchainTxHandler claim_id }, }; - debug_assert!(self.pending_claim_requests.get(&claim_id).is_none()); + // Because fuzzing can cause hash collisions, we can end up with conflicting claim + // ids here, so we only assert when not fuzzing. + debug_assert!(cfg!(fuzzing) || self.pending_claim_requests.get(&claim_id).is_none()); for k in req.outpoints() { log_info!(logger, "Registering claiming request for {}:{}", k.txid, k.vout); self.claimable_outpoints.insert(k.clone(), (claim_id, conf_height)); @@ -809,16 +826,15 @@ impl OnchainTxHandler /// `conf_height` represents the height at which the transactions in `txn_matched` were /// confirmed. This does not need to equal the current blockchain tip height, which should be /// provided via `cur_height`, however it must never be higher than `cur_height`. - pub(crate) fn update_claims_view_from_matched_txn( + pub(super) fn update_claims_view_from_matched_txn( &mut self, txn_matched: &[&Transaction], conf_height: u32, conf_hash: BlockHash, cur_height: u32, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, - L::Target: Logger, { log_debug!(logger, "Updating claims view at height {} with {} matched transactions in block {}", cur_height, txn_matched.len(), conf_height); - let mut bump_candidates = HashMap::new(); + let mut bump_candidates = new_hash_map(); for tx in txn_matched { // Scan all input to verify is one of the outpoint spent is of interest for us let mut claimed_outputs_material = Vec::new(); @@ -977,16 +993,15 @@ impl OnchainTxHandler } } - pub(crate) fn transaction_unconfirmed( + pub(super) fn transaction_unconfirmed( &mut self, txid: &Txid, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator, - logger: L, + logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, - L::Target: Logger, { let mut height = None; for entry in self.onchain_events_awaiting_threshold_conf.iter() { @@ -1001,12 +1016,11 @@ impl OnchainTxHandler } } - pub(crate) fn block_disconnected(&mut self, height: u32, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator, logger: L) + pub(super) fn block_disconnected(&mut self, height: u32, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L) where B::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, + F::Target: FeeEstimator, { - let mut bump_candidates = HashMap::new(); + let mut bump_candidates = new_hash_map(); let onchain_events_awaiting_threshold_conf = self.onchain_events_awaiting_threshold_conf.drain(..).collect::>(); for entry in onchain_events_awaiting_threshold_conf { @@ -1034,7 +1048,7 @@ impl OnchainTxHandler // `height` is the height being disconnected, so our `current_height` is 1 lower. let current_height = height - 1; if let Some((new_timer, new_feerate, bump_claim)) = self.generate_claim( - current_height, &request, true /* force_feerate_bump */, fee_estimator, &&*logger + current_height, &request, true /* force_feerate_bump */, fee_estimator, logger ) { request.set_timer(new_timer); request.set_feerate(new_feerate);