use bitcoin::secp256k1;
use ln::msgs::DecodeError;
-use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
use ln::channelmanager::PaymentPreimage;
use ln::chan_utils;
use ln::chan_utils::{TxCreationKeys, HolderCommitmentTransaction};
use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
+use chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
use chain::keysinterface::ChannelKeys;
use util::logger::Logger;
use util::ser::{Readable, Writer, Writeable};
onchain_events_waiting_threshold_conf: HashMap<u32, Vec<OnchainEvent>>,
+ latest_height: u32,
+
secp_ctx: Secp256k1<secp256k1::All>,
}
}
}
}
+ self.latest_height.write(writer)?;
Ok(())
}
}
}
onchain_events_waiting_threshold_conf.insert(height_target, events);
}
+ let latest_height = Readable::read(reader)?;
Ok(OnchainTxHandler {
destination_script,
claimable_outpoints,
pending_claim_requests,
onchain_events_waiting_threshold_conf,
+ latest_height,
secp_ctx: Secp256k1::new(),
})
}
}
impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
- pub(super) fn new(destination_script: Script, keys: ChanSigner, on_holder_tx_csv: u16) -> Self {
+ pub(crate) fn new(destination_script: Script, keys: ChanSigner, on_holder_tx_csv: u16) -> Self {
let key_storage = keys;
pending_claim_requests: HashMap::new(),
claimable_outpoints: HashMap::new(),
onchain_events_waiting_threshold_conf: HashMap::new(),
+ latest_height: 0,
secp_ctx: Secp256k1::new(),
}
}
- pub(super) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
+ pub(crate) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
let mut tx_weight = 2; // count segwit flags
for inp in inputs {
// We use expected weight (and not actual) as signatures and time lock delays may vary
/// Lightning security model (i.e being able to redeem/timeout HTLC or penalize coutnerparty onchain) lays on the assumption of claim transactions getting confirmed before timelock expiration
/// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent.
- fn generate_claim_tx<F: Deref, L: Deref>(&mut self, height: u32, cached_claim_datas: &ClaimTxBumpMaterial, fee_estimator: F, logger: L) -> Option<(Option<u32>, u32, Transaction)>
+ fn generate_claim_tx<F: Deref, L: Deref>(&mut self, height: u32, cached_claim_datas: &ClaimTxBumpMaterial, fee_estimator: &F, logger: &L) -> Option<(Option<u32>, u32, Transaction)>
where F::Target: FeeEstimator,
L::Target: Logger,
{
None
}
- pub(super) fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], claimable_outpoints: Vec<ClaimRequest>, height: u32, broadcaster: B, fee_estimator: F, logger: L)
+ /// 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.
+ /// Formerly this was named `block_connected`, but it is now also used for claiming an HTLC output
+ /// if we receive a preimage after force-close.
+ pub(crate) fn update_claims_view<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], claimable_outpoints: Vec<ClaimRequest>, latest_height: Option<u32>, broadcaster: &B, fee_estimator: &F, logger: &L)
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
{
- log_trace!(logger, "Block at height {} connected with {} claim requests", height, claimable_outpoints.len());
+ let height = match latest_height {
+ Some(h) => h,
+ None => self.latest_height,
+ };
+ log_trace!(logger, "Updating claims view at height {} with {} matched transactions and {} claim requests", height, txn_matched.len(), claimable_outpoints.len());
let mut new_claims = Vec::new();
let mut aggregated_claim = HashMap::new();
let mut aggregated_soonest = ::std::u32::MAX;
}
}
- pub(super) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: F, logger: L)
+ pub(crate) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: F, logger: L)
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
}
}
for (_, claim_material) in bump_candidates.iter_mut() {
- if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &claim_material, &*fee_estimator, &*logger) {
+ if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &claim_material, &&*fee_estimator, &&*logger) {
claim_material.height_timer = new_timer;
claim_material.feerate_previous = new_feerate;
broadcaster.broadcast_transaction(&bump_tx);
}
}
- pub(super) fn provide_latest_holder_tx(&mut self, tx: HolderCommitmentTransaction) -> Result<(), ()> {
- // To prevent any unsafe state discrepancy between offchain and onchain, once holder
- // commitment transaction has been signed due to an event (either block height for
- // HTLC-timeout or channel force-closure), don't allow any further update of holder
- // commitment transaction view to avoid delivery of revocation secret to counterparty
- // for the aformentionned signed transaction.
- if self.holder_htlc_sigs.is_some() || self.prev_holder_htlc_sigs.is_some() {
- return Err(());
- }
+ pub(crate) fn provide_latest_holder_tx(&mut self, tx: HolderCommitmentTransaction) {
self.prev_holder_commitment = self.holder_commitment.take();
self.holder_commitment = Some(tx);
- Ok(())
}
fn sign_latest_holder_htlcs(&mut self) {
// have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
// before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
// to monitor before.
- pub(super) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
+ pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
if let Some(ref mut holder_commitment) = self.holder_commitment {
match self.key_storage.sign_holder_commitment(holder_commitment, &self.secp_ctx) {
Ok(sig) => Some(holder_commitment.add_holder_sig(funding_redeemscript, sig)),
}
#[cfg(any(test, feature="unsafe_revoked_tx_signing"))]
- pub(super) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
+ pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
if let Some(ref mut holder_commitment) = self.holder_commitment {
let holder_commitment = holder_commitment.clone();
match self.key_storage.sign_holder_commitment(&holder_commitment, &self.secp_ctx) {
}
}
- pub(super) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
+ pub(crate) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
let mut htlc_tx = None;
if self.holder_commitment.is_some() {
let commitment_txid = self.holder_commitment.as_ref().unwrap().txid();
}
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
- pub(super) fn unsafe_get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
+ pub(crate) fn unsafe_get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
let latest_had_sigs = self.holder_htlc_sigs.is_some();
let prev_had_sigs = self.prev_holder_htlc_sigs.is_some();
let ret = self.get_fully_signed_htlc_tx(outp, preimage);